.NET Core利用動態(tài)代理實現(xiàn)AOP(面向切面編程)
1.介紹
1.1 動態(tài)代理作用
用動態(tài)代理可以做AOP(面向切面編程),進行無入侵式實現(xiàn)自己的擴展業(yè)務,調用者和被調用者之間的解耦,提高代碼的靈活性和可擴展性,比如:日志記錄、性能統(tǒng)計、安全控制、事務處理、異常處理等等。本方式實現(xiàn)思路用的.NET Core原生的DispatchProxy類,再加《特性標記》+《Handle接口》達到無入侵式擴展 ,有興趣的朋友,自行改進一下,封裝成組件。
有什么做的不好的或者建議,希望大家及時提出,幫助改進。
代碼上傳在gitee:https://gitee.com/luoxiangbao/dynamic-proxy.git
1.2 原生DispatchProxy類介紹
DispatchProxy我去看了一下源碼,和我設想的差不多,就是Emit類庫直接編寫IL語言,動態(tài)生成類和方法,然后在方法里調用Invoke方法,這個時候就我們只需要重寫Invoke方法,具體實現(xiàn)由我們自己管控。其性能很高,幾乎和我們寫好的C#編譯成IL沒多大區(qū)別,大家用的Autofac的AOP,我也看了一下,底層用的是Castle.Core類庫,而Castle.Core底層還是用的Emit方式實現(xiàn),只是思路不同。
便于理解我給大家貼一下源碼:
1.定義抽象DispatchProxy類的Invoke元數(shù)據(jù)

2.Emit類庫直接編寫IL語言,為代理類添加調用Invoke方法代碼

1.3簡單介紹一下:IL代碼
IL是.NET框架中間語言(Intermediate Language),編譯器可以直接將源程序編譯為.exe或.dll文件,而CLR(公共語言運行時)執(zhí)行的是IL語言,不是C#高級編程語言,IL代碼是一種近似于指令式的代碼語言,與匯編語言比較相近,給大家做個案例對比一下。
C#代碼:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}IL代碼:
IL_0000: nop IL_0001: ldstr "Hello World!" IL_0006: call void [System.Console]System.Console::WriteLine(string) IL_000b: nop IL_000c: ret
有興趣的朋友自己也可以去實現(xiàn)。接下來進入正題,我們怎么利用DispatchProxy自己造輪子!?。?/p>
2.實現(xiàn)
2.1 繼承DispatchProxy
核心類就是,DispatchProxy。這是.NET core 原生的。會幫我們創(chuàng)建一個代理類
internal class DynamicProxy<T> : DispatchProxy
{
public T? decorated { get; set; }//目標類
public Action<object?[]?>? _afterAction { get; set; } // 動作之后執(zhí)行
public Action<object?[]?, object>? _beforeAction { get; set; } // 動作之前執(zhí)行
protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
{
Exception exception = null;
AfterAction(args);
object result = null;
try
{
//調用實際目標對象的方法
result = targetMethod?.Invoke(decorated, args);
}
catch (Exception ex)
{
exception = ex;
}
BeforeAction(args, result);
//調用完執(zhí)行方法后的委托,如果有異常,拋出異常
if (exception != null)
{
throw exception;
}
return result;
}
/// <summary>
/// 創(chuàng)建代理實例
/// </summary>
/// <param name="decorated">代理的接口類型</param>
/// <param name="afterAction">方法執(zhí)行前執(zhí)行的事件</param>
/// <param name="beforeAction">方法執(zhí)行后執(zhí)行的事件</param>
/// <returns></returns>
public T Create(T decorated, Action<object?[]?> afterAction, Action<object?[]?, object> beforeAction)
{
object proxy = Create<T, DynamicProxy<T>>(); // 調用DispatchProxy 的Create 創(chuàng)建一個新的T
DynamicProxy<T> proxyDecorator = (DynamicProxy<T>)proxy;
proxyDecorator.decorated = decorated;
//把自定義的方法委托給代理類
proxyDecorator._afterAction = afterAction;
proxyDecorator._beforeAction = beforeAction;
return (T)proxy;
}
private void AfterAction(object?[]? args)
{
try
{
_afterAction.Invoke(args);
}
catch (Exception ex)
{
Console.WriteLine($"執(zhí)行之前異常:{ex.Message},{ex.StackTrace}");
}
}
private void BeforeAction(object?[]? args, object? result)
{
try
{
_beforeAction.Invoke(args, result);
}
catch (Exception ex)
{
Console.WriteLine($"執(zhí)行之后異常:{ex.Message},{ex.StackTrace}");
}
}
}2.2 定義handle接口
這個接口定義:執(zhí)行之前、執(zhí)行之后兩個方法。用來實現(xiàn)具體業(yè)務邏輯的處理
internal interface IInterceptor
{
/// <summary>
/// 執(zhí)行之前
/// </summary>
/// <param name="args">參數(shù)</param>
void AfterAction(object?[]? args);
/// <summary>
/// 執(zhí)行之后
/// </summary>
/// <param name="args">參數(shù)</param>
/// <param name="result">結果</param>
void BeforeAction(object?[]? args, object result);
}2.3 定義AOP特性
1.用來標記類具體使用哪個handle的實現(xiàn)來處理業(yè)務。
2. 特性定義Type屬性決定創(chuàng)建代理類的時候,具體使用哪個handle實現(xiàn)
[AttributeUsage(AttributeTargets.Class)]
internal class InterceptAttribut : Attribute
{
public Type Type { get; set; }
public InterceptAttribut(Type type)
{
this.Type = type;
}
}2.4 定義創(chuàng)建代理類的工廠
這里就是來組裝代理類與handle實現(xiàn)的地方。
internal class ProxyFactory
{
/// <summary>
/// 創(chuàng)建代理實例
/// </summary>
/// <param name="decorated">代理的接口類型</param>
/// <returns></returns>
public static T Create<T>()
{
var decorated = ServiceHelp.GetService<T>();
var type = decorated.GetType();
var interceptAttribut = type.GetCustomAttribute<InterceptAttribut>();
var interceptor = ServiceHelp.GetService<IInterceptor>(interceptAttribut.Type);
//創(chuàng)建代理類
var proxy = new DynamicProxy<T>().Create(decorated, interceptor.AfterAction, interceptor.BeforeAction);
return proxy;
}
}1.拿到具體類,獲取Type,獲取我們上面定義的特性,通過特性的屬性,用來創(chuàng)建handle實例
2.ServiceHelp是我定義的一個來獲取實例化的容器幫助類。這個用.NET CORE 原始的IOC。大家可替換成autofac
3.創(chuàng)建化代理實例,把實例和handle實現(xiàn)的具體方法:AfterAction、BeforeAction傳入。用于代理類執(zhí)行的時候,進行真正的調用
2.5 定義ServiceHelp
這里大家可自行發(fā)揮
public static class ServiceHelp
{
public static IServiceProvider? serviceProvider { get; set; }
public static void BuildServiceProvider(IServiceCollection serviceCollection)
{
//構建容器
serviceProvider = serviceCollection.BuildServiceProvider();
}
public static T GetService<T>(Type serviceType)
{
return (T)serviceProvider.GetService(serviceType);
}
public static T GetService<T>()
{
return serviceProvider.GetService<T>();
}
}3.測試
3.1 定義handle實現(xiàn)
internal class AOPTest : IInterceptor
{
public void AfterAction(object?[]? args)
{
Console.WriteLine($"AOP方法執(zhí)行之前,args:{args}");
throw new Exception("異常測試(異常,但依然不能影響程序執(zhí)行)");
}
public void BeforeAction(object?[]? args, object result)
{
Console.WriteLine($"AOP方法執(zhí)行之后,args:{args},result:{result}");
}
}3.2 定義Service接口
internal interface ITestService
{
public int Add(int a, int b);
}3.3實現(xiàn)Service接口
定義實現(xiàn),并且在類上加上,AOP交給哪個handle
[InterceptAttribut(typeof(AOPTest))]
internal class TestService : ITestService
{
public int Add(int a, int b)
{
Console.WriteLine($"正在執(zhí)行--》Add({a},)");
throw new Exception("方法執(zhí)行--》測試異常");
return a + b;
}
}3.4 大功告成
1.創(chuàng)建容器,把我們自己的業(yè)務實現(xiàn)都注冊好
2.通過工廠進行,動態(tài)創(chuàng)建代理實例
// See https://aka.ms/new-console-template for more information
using Infrastructure.DynamicProxy;
using Microsoft.Extensions.DependencyInjection;
Console.WriteLine("Hello, World!");
//容器注冊
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddTransient(typeof(AOPTest));
serviceCollection.AddTransient<ITestService, TestService>();
//構建容器
ServiceHelp.BuildServiceProvider(serviceCollection);
//用工廠獲取代理實例
var s = ProxyFactory.Create<ITestService>();
var sum = s.Add(1, 2);
Console.WriteLine("執(zhí)行完畢=====>" + sum);3.5 效果

4.Demo
大家可直接訪問我的,gitee
https://gitee.com/luoxiangbao/dynamic-proxy.git
以上就是.NET Core利用動態(tài)代理實現(xiàn)AOP(面向切面編程)的詳細內容,更多關于.NET Core實現(xiàn)AOP的資料請關注腳本之家其它相關文章!
相關文章
.net core如何利用ConcurrentTest組件對方法進行壓力測試詳解
這篇文章主要給大家介紹了關于.net core如何利用ConcurrentTest組件對方法進行壓力測試的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起看看吧2018-11-11
asp.net Parameters.AddWithValue方法在SQL語句的 Where 字句中的用法
今天晚上看論壇,有人提問說,Parameters.AddWithValue方法在有些情況下不好使2009-01-01
ASP.NET網(wǎng)頁打印(只打印相關內容/自寫功能)
朋友要求在前段時間完成的新聞的網(wǎng)站上加上一個功能,就是在每篇新聞瀏覽的頁面, 加一個打印銨鈕。讓用戶一點打印,能把整篇文章打印2013-01-01

