.NET Core類庫System.Reflection.DispatchProxy實(shí)現(xiàn)簡易Aop的方法
前言
aop即是面向切面編程,眾多Aop框架里Castle是最為人所知的,另外還有死去的Spring.NET,當(dāng)然,.NET Core社區(qū)新秀AspectCore在性能與功能上都非常優(yōu)秀,已經(jīng)逐漸被社區(qū)推崇和有越來越多的人使用。感謝檸檬同學(xué)的禮物!
如果大家出于自身需求或者學(xué)習(xí),想實(shí)現(xiàn)一個(gè)Aop,是不是覺得一來就要使用Emit去做?最近我了解到了System.Reflection.DispatchProxy這個(gè)corefx類庫,已經(jīng)實(shí)現(xiàn)了動(dòng)態(tài)代理功能。
1|1System.Reflection.DispatchProxy
下面演示一下它的使用方法:
class Program
{
static void Main(string[] args)
{
//創(chuàng)建代理類,并把SampleProxy作為攔截器注入
var sampleProxy = (targetInterface)SampleProxy.Create<targetInterface, SampleProxy>();
//執(zhí)行接口方法
sampleProxy.Write("here is invoke by proxy");
}
}
//需要被生成代理實(shí)例的接口
public interface targetInterface
{
//這個(gè)方法會(huì)被代理類實(shí)現(xiàn)
void Write(string writesomeshing);
}
public class SampleProxy : DispatchProxy
{
/// <summary>
/// 攔截調(diào)用
/// </summary>
/// <param name="method">所攔截的方法信息</param>
/// <param name="parameters">所攔截方法被傳入的參數(shù)指</param>
/// <returns></returns>
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
Console.WriteLine(args[0]);
return null;
}
}
2|0改造成一款簡易AOP
2|1為什么?
System.Reflection.DispatchProxy只有一個(gè)Api,就是objecct Create<T,TProxy>() where TProxy:DispatchProxy,約束了只能傳入泛型參數(shù),并不能從方法傳入類型,這就會(huì)帶來很多問題。而更可氣的是,給官方提了issue之后,還是不給增加這個(gè)api……
2|2改造方法
幸好,在那個(gè)issue下,issue作者提供了一個(gè)解決方案,就是用反射來構(gòu)造這個(gè)泛型方法。我還在這基礎(chǔ)上,封裝了一下,加入了傳入攔截器實(shí)例和傳入攔截器構(gòu)造方法參數(shù)的功能。
/// <summary>
/// 攔截器接口
/// </summary>
public interface IInterceptor
{
/// <summary>
/// 攔截器調(diào)用
/// </summary>
/// <param name="target">代理實(shí)例</param>
/// <param name="method">所攔截的方法</param>
/// <param name="parameters">所攔截方法傳入的參數(shù)值</param>
/// <returns>返回值會(huì)傳遞給方法返回值</returns>
object Intercept(object target, MethodInfo method, object[] parameters);
}
攔截器要實(shí)現(xiàn)這個(gè)接口,下面是對(duì)DispatchProxy的封裝,實(shí)現(xiàn)更多創(chuàng)建代理實(shí)例的方法
public class ProxyGenerator : DispatchProxy
{
private IInterceptor interceptor { get; set; }
/// <summary>
/// 創(chuàng)建代理實(shí)例
/// </summary>
/// <param name="targetType">所要代理的接口類型</param>
/// <param name="interceptor">攔截器</param>
/// <returns>代理實(shí)例</returns>
public static object Create(Type targetType, IInterceptor interceptor)
{
object proxy = GetProxy(targetType);
((ProxyGenerator)proxy).CreateInstance(interceptor);
return proxy;
}
/// <summary>
/// 創(chuàng)建代理實(shí)例
/// </summary>
/// <param name="targetType">所要代理的接口類型</param>
/// <param name="interceptorType">攔截器類型</param>
/// <param name="parameters">攔截器構(gòu)造函數(shù)參數(shù)值</param>
/// <returns>代理實(shí)例</returns>
public static object Create(Type targetType, Type interceptorType, params object[] parameters)
{
object proxy = GetProxy(targetType);
((ProxyGenerator)proxy).CreateInstance(interceptorType, parameters);
return proxy;
}
/// <summary>
/// 創(chuàng)建代理實(shí)例 TTarget:所要代理的接口類型 TInterceptor:攔截器類型
/// </summary>
/// <param name="parameters">攔截器構(gòu)造函數(shù)參數(shù)值</param>
/// <returns>代理實(shí)例</returns>
public static TTarget Create<TTarget, TInterceptor>(params object[] parameters) where TInterceptor : IInterceptor
{
var proxy = GetProxy(typeof(TTarget));
((ProxyGenerator)proxy).CreateInstance(typeof(TInterceptor), parameters);
return (TTarget)proxy;
}
private static object GetProxy(Type targetType)
{
var callexp = Expression.Call(typeof(DispatchProxy), nameof(DispatchProxy.Create), new[] { targetType, typeof(ProxyGenerator) });
return Expression.Lambda<Func<object>>(callexp).Compile()();
}
private void CreateInstance(Type interceptorType, object[] parameters)
{
var ctorParams = parameters.Select(x => x.GetType()).ToArray();
var paramsExp = parameters.Select(x => Expression.Constant(x));
var newExp = Expression.New(interceptorType.GetConstructor(ctorParams), paramsExp);
this.interceptor = Expression.Lambda<Func<IInterceptor>>(newExp).Compile()();
}
private void CreateInstance(IInterceptor interceptor)
{
this.interceptor = interceptor;
}
protected override object Invoke(MethodInfo method, object[] parameters)
{
return this.interceptor.Intercept(method, parameters);
}
}
2|3使用方法
class Program
{
static void Main(string[] args)
{
var poxy1 = (targetInterface)ProxyGenerator.Create(typeof(targetInterface), new SampleProxy("coreproxy1"));
poxy1.Write("here was invoked"); //---> "here was invoked by coreproxy1"
var poxy2 = (targetInterface)ProxyGenerator.Create(typeof(targetInterface), typeof(SampleProxy), "coreproxy2");
poxy2.Write("here was invoked"); //---> "here was invoked by coreproxy2"
var poxy3 = ProxyGenerator.Create<targetInterface, SampleProxy>("coreproxy3");
poxy3.Write("here was invoked"); //---> "here was invoked by coreproxy3"
}
}
public class SampleProxy : IInterceptor
{
private string proxyName { get; }
public SampleProxy(string name)
{
this.proxyName = name;
}
public object Intercept(MethodInfo method, object[] parameters)
{
Console.WriteLine(parameters[0] + " by " + proxyName);
return null;
}
}
public interface targetInterface
{
void Write(string writesome);
}
3|0總結(jié)
總結(jié)一下就是,微軟爸爸給我們的這個(gè)輪子還是即輕便又很好用的。
本文的實(shí)例代碼可以在我的github上找到:https://github.com/ElderJames/CoreProxy
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
ASP.NET MVC5+EF6+EasyUI 后臺(tái)管理系統(tǒng)(81)-數(shù)據(jù)篩選(萬能查詢)實(shí)例
本篇文章主要介紹了ASP.NET MVC5+EF6+EasyUI 后臺(tái)管理系統(tǒng)(81)-數(shù)據(jù)篩選(萬能查詢) ,具有一定的參考價(jià)值,有興趣的可以了解一下。2016-12-12
asp.net利用ashx文件實(shí)現(xiàn)文件的上傳功能
這篇文章主要介紹了asp.net利用ashx文件實(shí)現(xiàn)文件的上傳功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
從別人那拷下來的幾點(diǎn)Session使用的經(jīng)驗(yàn)
從別人那拷下來的幾點(diǎn)Session使用的經(jīng)驗(yàn)...2007-04-04
ASP.NET學(xué)習(xí)CORE中使用Cookie身份認(rèn)證方法
本篇文章主要給大家詳細(xì)分析了ASP.NET學(xué)習(xí)CORE中使用Cookie身份認(rèn)證方法以及相關(guān)的實(shí)例代碼,有需要的朋友參考下吧。2018-01-01
c# 連接字符串?dāng)?shù)據(jù)庫服務(wù)器端口號(hào) .net狀態(tài)服務(wù)器端口號(hào)
正常的數(shù)據(jù)庫連接字符串配置,這是在MSSQL服務(wù)器端口是1433(默認(rèn))的情況下。2009-06-06
詳解如何在ASP.Net Core中實(shí)現(xiàn)健康檢查
這篇文章主要介紹了詳解如何在ASP.Net Core中實(shí)現(xiàn)健康檢查,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
.NET Core 2.0遷移小技巧之web.config 配置文件示例詳解
這篇文章主要給大家介紹了關(guān)于.NET Core 2.0遷移技巧之web.config 配置文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08

