小白开学Asp.Net Core《四》

                              —— 使用AspectCore-Framework

一、AspectCore-Framework

 说AspectCore-Framework不得不先谈谈的AOP,

  AOP:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。(来自于百度百科)

  AspectCore-Framework 的具体介绍就不在这里造轮子了,下面列出几遍大佬们写的文章。

二、使用

  • Nuget 安装 Aspectcore 及相关组件

       小白开学Asp.Net Core 《四》-LMLPHP

   具体结合Redis来说明:

  Redis采用的是CSRedis

  • Nuget CsRedis 及相关组件的安装

 小白开学Asp.Net Core 《四》-LMLPHP

 下面就直接贴代码了

  •   分布式Redis缓存
 public class DistributedCacheManager
    {
        private static IDistributedCache Instance => AspectCoreContainer.Resolve<IDistributedCache>();

        public static string Get(string key)
        {
            if (RedisHelper.Exists(key))
            {
                return RedisHelper.Get(key);
            }

            return null;
        }

        public static async Task<string> GetAsync(string key)
        {
            if (await RedisHelper.ExistsAsync(key))
            {
                var content = await RedisHelper.GetAsync(key);
                return content;
            }

            return null;
        }

        public static T Get<T>(string key)
        {
            var value = Get(key);
            if (!string.IsNullOrEmpty(value))
                return JsonConvertor.Deserialize<T>(value);
            return default(T);
        }

        public static async Task<T> GetAsync<T>(string key)
        {
            var value = await GetAsync(key);
            if (!string.IsNullOrEmpty(value))
            {
                return JsonConvertor.Deserialize<T>(value);
            }

            return default(T);
        }

        public static void Set(string key, object data, int expiredSeconds)
        {
            RedisHelper.Set(key, JsonConvertor.Serialize(data), expiredSeconds);
        }

        public static async Task<bool> SetAsync(string key, object data, int expiredSeconds)
        {
            return await RedisHelper.SetAsync(key, JsonConvertor.Serialize(data), expiredSeconds);
        }


        public static void Remove(string key) => Instance.Remove(key);

        public static async Task RemoveAsync(string key) => await Instance.RemoveAsync(key);

        public static void Refresh(string key) => Instance.Refresh(key);

        public static async Task RefreshAsync(string key) => await Instance.RefreshAsync(key);

        public static void Clear()
        {
            throw new NotImplementedException();
        }
    }
  • Aspectcore Framwork 动态代理Redis
    [AttributeUsage(AttributeTargets.Method)]
    public class RedisCacheAttribute : AbstractInterceptorAttribute
    {       
        public int Expiration { get; set; } = 10 * 60;

        public string CacheKey { get; set; } = null;

        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            var parameters = context.ServiceMethod.GetParameters();
            if (parameters.Any(it => it.IsIn || it.IsOut))
                await next(context);
            else
            {
                var key = string.IsNullOrEmpty(CacheKey)
                    ? new CacheKey(context.ServiceMethod, parameters, context.Parameters).GetRedisCacheKey()
                    : CacheKey;
                var value = await DistributedCacheManager.GetAsync(key);
                if (value != null)
                {
                    if (context.ServiceMethod.IsReturnTask())
                    {
                        dynamic result = JsonConvert.DeserializeObject(value,
                            context.ServiceMethod.ReturnType.GenericTypeArguments[0]);
                        context.ReturnValue = Task.FromResult(result);
                    }
                    else
                        context.ReturnValue = JsonConvert.DeserializeObject(value, context.ServiceMethod.ReturnType);
                }
                else
                {
                    await context.Invoke(next);
                    dynamic returnValue = context.ReturnValue;
                    if (context.ServiceMethod.IsReturnTask())
                        returnValue = returnValue.Result;
                    await DistributedCacheManager.SetAsync(key, returnValue, Expiration);
                }
            }
        }
    }
  • CSRedis 服务注册
public static IServiceCollection UseCsRedisClient(this IServiceCollection services, params string[] redisConnectionStrings)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            if (redisConnectionStrings == null || redisConnectionStrings.Length == 0)
                throw new ArgumentNullException(nameof(redisConnectionStrings));
            CSRedisClient redisClient;
            if (redisConnectionStrings.Length == 1)
                //单机模式
                redisClient = new CSRedisClient(redisConnectionStrings[0]);
            else
                //集群模式
                redisClient = new CSRedisClient(NodeRule: null, connectionStrings: redisConnectionStrings);
            //初始化 RedisHelper
            RedisHelper.Initialization(redisClient);
            //注册mvc分布式缓存
            services.AddSingleton<IDistributedCache>(new Microsoft.Extensions.Caching.Redis.CSRedisCache(RedisHelper.Instance));
            return services;
        }
  • .Net Core Startup.cs 中注册服务
   var redisConnectionString = Configuration.GetConnectionString("Redis");
            //启用Redis
            services.UseCsRedisClient(redisConnectionString);

 return AspectCoreContainer.BuildServiceProvider(services);//接入AspectCore.Injector
  • 具体使用
    • 简单的直接在Controller中使用 

            小白开学Asp.Net Core 《四》-LMLPHP

    •  在服务中使用

         小白开学Asp.Net Core 《四》-LMLPHP

三、补充说明

  1、Redis 客户端安装本文默认都已安装

       2、一定要在Startup.cs 的 ConfigureServices 方法中进行服务的注册,并使用 return AspectCoreContainer.BuildServiceProvider(services); 让AspectCore 接管,不是Aspectcore 是拦截不了的

       3、按照Aspectcore 的官方文档来说,需要加特性的方法必须是虚方法,也就是必须加virtual 修饰。不然不会被调用

       4、本文只是用Redis缓存来说名使用AOP(Aspectcore Framwork)的一方面,并不是说只能用于 Redis ,其他的(如 日志记录等)都可以使用的

       5、代码源码全部在Github上

(本人坚信:学习是由浅到深的过程,先打基础)

    不喜勿喷!谢谢!

  GitHub地址: https://github.com/AjuPrince/Aju.Carefree

小白开学Asp.Net Core 《四》-LMLPHP

07-06 16:31