AspectCore Cache interceptor 缓存拦截器

添加一个 package Microsoft.Extensions.Caching.Memory 5.0.0

版本我们选择5.0.0 (因为) 目前 AspectCore 依赖 Microsoft.Extensions.DependencyInjection 的版本是5.0.0 如何使用6.0

并且在Di里面引用

using AspectCore.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
namespace Malema.Net;
public class DIConfig
{
    public static IServiceProvider GetServiceProvider()
    {
        var services = new ServiceCollection();

        services.AddScoped<ITestService, TestService>();
        // 注入IMemoryCache。下面的  CacheInterceptorAttribute 会用到它
        services.AddMemoryCache(); 

        //return services.BuildServiceProvider();
        return services.BuildDynamicProxyProvider();
    }
}

写一个 Cache 拦截器 CacheInterceptorAttribute

using AspectCore.DynamicProxy;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using System.Text;

namespace Malema.Net;
public class CacheInterceptorAttribute : AbstractInterceptorAttribute
{
    public override async Task Invoke(AspectContext context, AspectDelegate next)
    {
        var methodName = context.ImplementationMethod.DeclaringType + context.ImplementationMethod.Name;

        var sb = new StringBuilder();
        foreach (var item in context.ServiceMethod.GetParameters())
        {
            sb.Append(item.Name);
        }
        foreach (var value in context.Parameters)
        {
            sb.Append(value.GetHashCode());
        }
        var cacheKey = methodName + sb.ToString();

        var cache = context.ServiceProvider.GetService<IMemoryCache>(); //在容器当中取出 IMemoryCache
        var result = await cache.GetOrCreateAsync(cacheKey, async (entry) =>
        {
            await next(context);
            var returnValue = context.ReturnValue;

            return returnValue;
        });
        context.ReturnValue = result;
    }
}

修改我们的测试类

namespace Malema.Net;
public interface ITestService
{
    string TestCache(int age);

    Task<string> TestCacheAsync(int age);
}

namespace Malema.Net;
public class TestService : ITestService
{
    [CacheInterceptor]
    public string TestCache(int age)
    {
        Console.WriteLine("TestCache");
        return (age + 100).ToString();
    }

// Async方法也是支持的。
    [CacheInterceptor]
    public async Task<string> TestCacheAsync(int age)
    {
        Console.WriteLine("TestCacheAsync");
        return (age + 200).ToString();
    }
}

修改 Program.cs

using Malema.Net;
using Microsoft.Extensions.DependencyInjection;


var sp = DIConfig.GetServiceProvider();
var service = sp.GetService<ITestService>();
var name = service.TestCache(30);
var name2 = service.TestCache(30);
Console.WriteLine($"Done {name2}");

name = await service.TestCacheAsync(30);
name2 = await service.TestCacheAsync(30);
Console.WriteLine($"Async Done {name2}");
Console.ReadKey();

输出

TestCache
Done 130
TestCacheAsync
Async Done 230

TestCache和TestCacheAsync只输出一次。其它值是从Cache当中获取的

完整的代码在https://gitee.com/malema/Examples/tree/AspectCore%2FCache/AspectCore-Example这边可以看到 可以用下面的git命令把代码签出到本地

git clone https://gitee.com/malema/Examples
git checkout AspectCore/Cache

如何解决引用版本冲突

如果引用 Microsoft.Extensions.Caching.Memory 6.0.0 我们会发现编译的时候会出现如下的错误

 类型“ServiceCollection”同时存在于“Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60”
 和“Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60”中

如何解决这个错呢?

.Net的库很多时候是会兼容旧的。所以上面如果想使用 Microsoft.Extensions.Caching.Memory 6.0.0的版本的话

我们可以使用Nuget添加一个新的Package Microsoft.Extensions.DependencyInjection 6.0.0

这样上面的错误就会被解决了。

最近更新的
...