欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# 使用 Castle 實(shí)現(xiàn) AOP及如何用 Autofac 集成 Castle

 更新時(shí)間:2021年02月25日 10:29:15   作者:丹楓無跡  
這篇文章主要介紹了C# 使用 Castle 實(shí)現(xiàn) AOP及如何用 Autofac 集成 Castle,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下

Castle 是 2003 年誕生于 Apache Avalon 項(xiàng)目,目的是為了創(chuàng)建一個(gè)IOC 框架。發(fā)展到現(xiàn)在已經(jīng)有四個(gè)組件:

  • ORM組件:ActiveRecord
  • IOC組件:Windsor
  • 動(dòng)態(tài)代理組件:DynamicProxy
  • Web MVC組件:MonoRail

本文主要介紹 動(dòng)態(tài)代理組件 Castle.DynamicProxy

基本用法

Castle.DynamicProxy 是通過 Emit 反射動(dòng)態(tài)生成代理類來實(shí)現(xiàn)的,效率相對靜態(tài)植入要慢一點(diǎn),但比普通的反射又高一些。動(dòng)態(tài)代理只對公共接口方法、類中的虛方法生效,因?yàn)橹挥薪涌谥械姆椒ā㈩愔械奶摲椒ú趴梢栽谧宇愔兄貙憽?/p>

基于接口的攔截器

public interface IProductRepository
{
 void Add(string name);
}

public class ProductRepository : IProductRepository
{
 public void Add(string name) => Console.WriteLine($"新增產(chǎn)品:{name}");
}

public class LoggerInterceptor : IInterceptor
{
 public void Intercept(IInvocation invocation)
 {
  var methodName = invocation.Method.Name;

  Console.WriteLine($"{methodName} 執(zhí)行前");

  //調(diào)用業(yè)務(wù)方法
  invocation.Proceed();

  Console.WriteLine($"{methodName} 執(zhí)行完畢");
 }
}

class Program
{
 static void Main(string[] args)
 {
  ProxyGenerator generator = new ProxyGenerator();

  IInterceptor loggerIntercept = new LoggerInterceptor();

  IProductRepository productRepo = new ProductRepository();

  IProductRepository proxy = generator.CreateInterfaceProxyWithTarget(productRepo, loggerIntercept);

  proxy.Add("大米");

  Console.Read();
 }
}

基于類的攔截器

public class ProductRepository
{
 public virtual void Add(string name) => Console.WriteLine($"新增產(chǎn)品:{name}");
}

static void Main(string[] args)
{
 ProxyGenerator generator = new ProxyGenerator();

 IInterceptor loggerIntercept = new LoggerInterceptor();

 ProductRepository proxy = generator.CreateClassProxyWithTarget(new ProductRepository(), loggerIntercept);
 // 使用 CreateClassProxy 泛型方法可以省去實(shí)例化代碼
 //ProductRepository proxy = generator.CreateClassProxy<ProductRepository>(loggerIntercept);

 proxy.Add("大米");
}

在上例中,如果 ProductRepository.Add 不是虛方法,也不會(huì)報(bào)錯(cuò),但是攔截器不會(huì)被調(diào)用。

異步函數(shù)攔截

Castle.DynamicProxy 對異步函數(shù)的攔截跟同步?jīng)]啥差別,只是,如果要在方法執(zhí)行完成后插入內(nèi)容,需要 await

public class ProductRepository
{
 public virtual Task Add(string name)
 {
  return Task.Run(() =>
      {
       Thread.Sleep(1000);
       Console.WriteLine($"異步新增產(chǎn)品:{name}");
      });
 }
}

public class LoggerInterceptor : IInterceptor
{
 public async void Intercept(IInvocation invocation)
 {
  var methodName = invocation.Method.Name;

  Console.WriteLine($"{methodName} 執(zhí)行前");

  invocation.Proceed();

  // 不 await 的話將會(huì)先輸出“執(zhí)行完畢”,再輸出“異步新增產(chǎn)品”
  var task = (Task)invocation.ReturnValue;
  await task;

  Console.WriteLine($"{methodName} 執(zhí)行完畢");
 }
}

上面這個(gè)寫法是簡單粗暴的,如果碰到返回值是 Task<TResult>,或者不是異步函數(shù),就會(huì)出錯(cuò)。所以這里是要對返回值進(jìn)行一個(gè)判斷的。

可以使用 Castle.Core.AsyncInterceptor 包,它包裝了 Castle,使異步調(diào)用更簡單。

Castle.Core.AsyncInterceptor 的 GitHub 地址:https://github.com/JSkimming/Castle.Core.AsyncInterceptor

public class ProductRepository : IProductRepository
{
 public Task Add(string name)
 {
  return Task.Run(() =>
      {
       Thread.Sleep(1000);
       Console.WriteLine($"異步新增產(chǎn)品:{name}");
      });
 }

 public Task<string> Get()
 {
  return Task.Run(() =>
      {
       Thread.Sleep(1000);
       Console.WriteLine($"獲取產(chǎn)品");

       return "大米";
      });
 }
}

public class LoggerInterceptor : IAsyncInterceptor
{
 public void InterceptAsynchronous(IInvocation invocation)
 {
  invocation.ReturnValue = InternalInterceptAsynchronous(invocation);
 }

 async Task InternalInterceptAsynchronous(IInvocation invocation)
 {
  var methodName = invocation.Method.Name;

  Console.WriteLine($"{methodName} 異步執(zhí)行前");

  invocation.Proceed();
  await (Task)invocation.ReturnValue;

  Console.WriteLine($"{methodName} 異步執(zhí)行完畢");
 }

 public void InterceptAsynchronous<TResult>(IInvocation invocation)
 {
  invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);

  Console.WriteLine(((Task<TResult>)invocation.ReturnValue).Id);
 }

 private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
 {
  var methodName = invocation.Method.Name;

  Console.WriteLine($"{methodName} 異步執(zhí)行前");

  invocation.Proceed();
  var task = (Task<TResult>)invocation.ReturnValue;
  TResult result = await task;

  Console.WriteLine(task.Id);

  Console.WriteLine($"{methodName} 異步執(zhí)行完畢");

  return result;
 }

 public void InterceptSynchronous(IInvocation invocation)
 {
  var methodName = invocation.Method.Name;

  Console.WriteLine($"{methodName} 同步執(zhí)行前");

  invocation.Proceed();

  Console.WriteLine($"{methodName} 同步執(zhí)行完畢");
 }
}

class Program
{
 static void Main(string[] args)
 {
  ProxyGenerator generator = new ProxyGenerator();

  IAsyncInterceptor loggerIntercept = new LoggerInterceptor();

  IProductRepository productRepo = new ProductRepository();

  IProductRepository proxy = generator.CreateInterfaceProxyWithTarget(productRepo, loggerIntercept);

  proxy.Get();
 }
}

這是 Castle.Core.AsyncInterceptor 提供的示例寫法,這里有個(gè)問題,也是我的疑惑。invocation.ReturnValue = InternalInterceptAsynchronous(invocation); 將導(dǎo)致代理返回的 Task 是一個(gè)新的 Task,這一點(diǎn)我們可以輸出 Task.Id 來確認(rèn)。個(gè)人感覺有點(diǎn)畫蛇添足。

public async void InterceptAsynchronous<TResult>(IInvocation invocation)
{
 var methodName = invocation.Method.Name;

 Console.WriteLine($"{methodName} 異步執(zhí)行前");

 invocation.Proceed();
 var task = (Task<TResult>)invocation.ReturnValue;
 await task;

 Console.WriteLine($"{methodName} 異步執(zhí)行完畢");
}

這樣就挺好的。

如果有小伙伴知道為什么要返回一個(gè)新的 Task,請留言告訴我,謝謝!

Autofac 集成

Autofac.Extras.DynamicProxy 是一個(gè) Autofac 擴(kuò)展,可與 Castle 一起提供 AOP 攔截。

基于接口的攔截器

static void Main(string[] args)
{
 ContainerBuilder builder = new ContainerBuilder();
 //注冊攔截器
 builder.RegisterType<LoggerInterceptor>().AsSelf();

 //注冊要攔截的服務(wù)
 builder.RegisterType<ProductRepository>().AsImplementedInterfaces()
  .EnableInterfaceInterceptors()     //啟用接口攔截
  .InterceptedBy(typeof(LoggerInterceptor));  //指定攔截器

 IContainer container = builder.Build();

 IProductRepository productRepo = container.Resolve<IProductRepository>();

 productRepo.Add("大米");
}

基于類的攔截器

static void Main(string[] args)
{
 ContainerBuilder builder = new ContainerBuilder();
 //注冊攔截器
 builder.RegisterType<LoggerInterceptor>().AsSelf();

 //注冊要攔截的服務(wù)
 builder.RegisterType<ProductRepository>()
  .EnableClassInterceptors()      //啟用類攔截
  .InterceptedBy(typeof(LoggerInterceptor));  //指定攔截器

 IContainer container = builder.Build();

 ProductRepository productRepo = container.Resolve<ProductRepository>();

 productRepo.Add("大米");
}

異步函數(shù)攔截

Castle.Core.AsyncInterceptor 中,IAsyncInterceptor 接口并不集成 IInterceptor 接口,而 Autofac.Extras.DynamicProxy 是綁定 Castle 的,所以按上面同步攔截的寫法是會(huì)報(bào)錯(cuò)的。

IAsyncInterceptor 提供了 ToInterceptor() 擴(kuò)展方法來進(jìn)行類型轉(zhuǎn)換。

public class LoggerInterceptor : IInterceptor
{
 readonly LoggerAsyncInterceptor interceptor;

 public LoggerInterceptor(LoggerAsyncInterceptor interceptor)
 {
  this.interceptor = interceptor;
 }

 public void Intercept(IInvocation invocation)
 {
  this.interceptor.ToInterceptor().Intercept(invocation);
 }
}

public class LoggerAsyncInterceptor : IAsyncInterceptor
{
 public void InterceptAsynchronous(IInvocation invocation)
 {
  //...
 }

 public void InterceptAsynchronous<TResult>(IInvocation invocation)
 {
  //...
 }

 public void InterceptSynchronous(IInvocation invocation)
 {
  //...
 }
}

static void Main(string[] args)
{
 ContainerBuilder builder = new ContainerBuilder();
 //注冊攔截器
 builder.RegisterType<LoggerInterceptor>().AsSelf();
 builder.RegisterType<LoggerAsyncInterceptor>().AsSelf();

 //注冊要攔截的服務(wù)
 builder.RegisterType<ProductRepository>().AsImplementedInterfaces()
  .EnableInterfaceInterceptors()     //啟用接口攔截
  .InterceptedBy(typeof(LoggerInterceptor));  //指定攔截器

 var container = builder.Build();

 IProductRepository productRepo = container.Resolve<IProductRepository>();

 productRepo.Get();
}

以上就是C# 使用 Castle 實(shí)現(xiàn) AOP及如何用 Autofac 集成 Castle的詳細(xì)內(nèi)容,更多關(guān)于C# 使用 Castle 實(shí)現(xiàn) AOP的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#中WPF顏色對話框控件的實(shí)現(xiàn)

    C#中WPF顏色對話框控件的實(shí)現(xiàn)

    在 C# WPF開發(fā)中顏色對話框控件(ColorDialog)用于對界面中的背景、文字…(擁有顏色屬性的所有控件)設(shè)置顏色,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C#讀取配置文件的方法匯總

    C#讀取配置文件的方法匯總

    本文給大家介紹的是使用C#讀取配置文件的方法,個(gè)人給大家總結(jié)了6種,余下的以后再更新,有需要的小伙伴可以參考下。
    2015-06-06
  • Unity實(shí)現(xiàn)卡片循環(huán)滾動(dòng)效果的示例詳解

    Unity實(shí)現(xiàn)卡片循環(huán)滾動(dòng)效果的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用Unity實(shí)現(xiàn)卡片循環(huán)滾動(dòng)的效果,文中的實(shí)現(xiàn)步驟講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下
    2022-12-12
  • Unity AssetBundle打包工具示例詳解

    Unity AssetBundle打包工具示例詳解

    這篇文章主要介紹了Unity AssetBundle打包工具,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • C#實(shí)現(xiàn)一個(gè)Word保護(hù)性模板文件

    C#實(shí)現(xiàn)一個(gè)Word保護(hù)性模板文件

    這篇文章主要為大家詳細(xì)介紹了C#如何實(shí)現(xiàn)一個(gè)Word保護(hù)性模板文件,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以參考一下
    2024-01-01
  • C#入?yún)⑹褂靡妙愋鸵觬ef的原因解析

    C#入?yún)⑹褂靡妙愋鸵觬ef的原因解析

    這篇文章主要介紹了C#入?yún)⑹褂靡妙愋鸵觬ef的原因解析,我們在實(shí)際開發(fā)中還是能夠碰到一些引用類型添加ref的場景,其實(shí)道理也是一樣的,就是將引用類型的棧的地址傳遞到了方法中,那么和不添加有啥區(qū)別,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • C# 控件屬性和InitializeComponent()關(guān)系案例詳解

    C# 控件屬性和InitializeComponent()關(guān)系案例詳解

    這篇文章主要介紹了C# 控件屬性和InitializeComponent()關(guān)系案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 關(guān)于C#中使用Oracle存儲(chǔ)過程返回結(jié)果集的問題

    關(guān)于C#中使用Oracle存儲(chǔ)過程返回結(jié)果集的問題

    Oracle中可以使用游標(biāo)(Cursor)對數(shù)據(jù)集進(jìn)行操作,但在存儲(chǔ)過程輸出參數(shù)中直接使用Cursor錯(cuò)誤,下面小編給大家?guī)砹薈#中使用Oracle存儲(chǔ)過程返回結(jié)果集的問題,感興趣的朋友一起看看吧
    2021-10-10
  • c# 動(dòng)態(tài)加載dll文件,并實(shí)現(xiàn)調(diào)用其中的方法(推薦)

    c# 動(dòng)態(tài)加載dll文件,并實(shí)現(xiàn)調(diào)用其中的方法(推薦)

    下面小編就為大家?guī)硪黄猚# 動(dòng)態(tài)加載dll文件,并實(shí)現(xiàn)調(diào)用其中的方法(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • C#中動(dòng)態(tài)數(shù)組用法實(shí)例

    C#中動(dòng)態(tài)數(shù)組用法實(shí)例

    這篇文章主要介紹了C#中動(dòng)態(tài)數(shù)組用法,實(shí)例分析了C#中ArrayList實(shí)現(xiàn)動(dòng)態(tài)數(shù)組的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04

最新評(píng)論