聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(二)
聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(二)
前言
前文排版比較糟糕,這次我們使用vscode來寫本文,,各位看客請見諒。
上文描述了 ServiceDescriptor 的三種構造形式,這決定了我們之后獲取原始對象要考慮的場景,至于如何獲取暫且不表,在實現細節部分我們會詳細闡述。
本文將闡述 _ProxyGenerator_的一些細節,以便各位看客更好理解 Castle 在各種場景下 如何選擇合適的接口去構建代理對象(以下全稱為代理對象或者 proxy)
代理對象的構建方法
大體分成兩種方式 一種是具體類 一種是根據接口生成代理對象,每種內部都會區分是否傳入原始對象 看方法簽名 WithTarget 即需要傳入 原始對象,WithoutTarget 即不需要傳入原始對象,
- ProxyGenerator.CreateClassProxy
- ProxyGenerator.CreateInterfaceProxy
示例說明
接下來我們以幾種示例來介紹各個接口的使用情況
- 假設已知 一個接口 ISampleService 和一個實現類 SampleService
public class SampleService : ISampleService
{
public virtual Task ShowAsync()
{
return Task.CompletedTask;
}
}
public interface ISampleService
{
Task ShowAsync();
}
public class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("Interceptor starting...");
invocation.Proceed();
Console.WriteLine("Interceptor ended...");
}
}
具體類
我們想對 SampleService 進行代理生成 因為 SampleService 具有無參構造,所以我們可以這樣
var generator=new ProxyGenerator();
var proxy = generator.CreateClassProxy(typeof(SampleService), new Interceptor());
假設 SampleService 有參數構造函數
public class SampleService : ISampleService
{
private readonly ILogger<SampleService> _logger;
public SampleService(ILogger<SampleService> logger)
{
_logger=logger;
}
public Task ShowAsync()
{
return Task.CompletedTask;
}
}
```,那么我們就可以這樣
``` csharp
var generator=new ProxyGenerator();
var sampleSvc=sp.GetRequiredService<SampleService>();
var proxy = generator.CreateClassProxyWithTarget(typeof(SampleService),sampleSvc, new Interceptor());
細心的朋友可能發現這時候我們引入了一個變量 而我們并未定義,
這時候我們添加如下代碼:
var services=new ServiceCollection();
services.AddLogging();//此處添加日志服務 偽代碼 以便獲取ILogger<SampleService>
services.AddSingleton<ProxyGenerator>(sp=>new ProxyGenerator());
servies.TryAddTransient<SampleService>();
var sp=services.BuildServiceProvider();
接口
使用以上代碼示例,假設我們要對 ISampleService 進行代理生成,那么我們就可以這樣
services.TryAddTransient<ISampleService, SampleService>();//注入階段添加以下代碼以便獲取ISampleService
var generator=sp.GetRequiredService<ProxyGenerator>();
var proxy=generator.CreateInterfaceProxyWithoutTarget(typeof(ISampleService),new Interceptor());//因為沒有傳入 原始對象,所以依然要求我們是一個無參構造的實現 TODO:可自行驗證
看下原始定義
假設我們獲取了 _ISampleService_的實例
var sampleSvc=sp.GetRequiredService<ISampleService>();
var proxy = generator.CreateInterfaceProxyWithTarget(typeof(ISampleService),sampleSvc, new Interceptor());
可以發現 接口代理 和具體類代理 基本相似
細心的可以注意到 SampleService.ShowAsync 很反常的 加了個關鍵字 virtual,想知道為什么,這里我們借用 Castle 的文檔 https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-introduction.md 有興趣的朋友可以自行查詢
總結
說到這里,我們已經基本了解了 castle構建動態代理的基本方法,接下來我們來總結一下代理對象的構建方法。 先區分目標是類還是接口,類的代理方法要求關鍵字virtual,無參構造可以使用 CreateClassProxy,有參數可以先獲取到原始對象,傳入 CreateClassProxyWithTarget;
接口同,無原始對象 CreateInterfaceProxyWithoutTarget ,有原始對象 CreateInterfaceProxyWithTarget。
代碼太多有點枯燥,本文先到這邊。
總結
以上是生活随笔為你收集整理的聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IPv6通过公网共享文件(Windows
- 下一篇: ClickHouse(21)ClickH