小白開學Asp.Net Core《四》
—— 使用AspectCore-Framework
一、AspectCore-Framework
說AspectCore-Framework不得不先談談的AOP,
AOP:在軟體業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,是函數語言程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。(來自於百度百科)
AspectCore-Framework 的具體介紹就不在這裡造輪子了,下面列出幾遍大佬們寫的文章。
二、使用
- Nuget 安裝 Aspectcore 及相關元件
具體結合Redis來說明:
Redis採用的是CSRedis
- Nuget CsRedis 及相關元件的安裝
下面就直接貼程式碼了
- 分散式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中使用
-
- 在服務中使用
三、補充說明
1、Redis 客戶端安裝本文預設都已安裝
2、一定要在Startup.cs 的 ConfigureServices 方法中進行服務的註冊,並使用 return AspectCoreContainer.BuildServiceProvider(services); 讓AspectCore 接管,不是Aspectcore 是攔截不了的
3、按照Aspectcore 的官方文件來說,需要加特性的方法必須是虛方法,也就是必須加virtual 修飾。不然不會被呼叫
4、本文只是用Redis快取來說名使用AOP(Aspectcore Framwork)的一方面,並不是說只能用於 Redis ,其他的(如 日誌記錄等)都可以使用的
5、程式碼原始碼全部在Github上
(本人堅信:學習是由淺到深的過程,先打基礎)
不喜勿噴!謝謝!