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