聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(二)
---
### 前言
前文排版比较糟糕,这次我们使用vscode来写本文,,各位看客请见谅。
上文描述了 _ServiceDescriptor_ 的三种构造形式,这决定了我们之后获取原始对象要考虑的场景,至于如何获取暂且不表,在实现细节部分我们会详细阐述。
本文将阐述 _ProxyGenerator_的一些细节,以便各位看客更好理解 _Castle_ 在各种场景下 如何选择合适的接口去构建代理对象(以下全称为代理对象或者 _proxy_)
### 代理对象的构建方法
大体分成两种方式 一种是具体类 一种是根据接口生成代理对象,每种内部都会区分是否传入原始对象 看方法签名 _WithTarget_ 即需要传入 原始对象,_WithoutTarget_ 即不需要传入原始对象,
* _ProxyGenerator.CreateClassProxy_
* _ProxyGenerator.CreateInterfaceProxy_
### 示例说明
接下来我们以几种示例来介绍各个接口的使用情况
* 假设已知 一个接口 _ISampleService_ 和一个实现类 _SampleService_
```csharp
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...");
}
}
```
#### 具体类
![Alt text](image.png)
我们想对 _SampleService_ 进行代理生成 因为 _SampleService_ 具有无参构造,所以我们可以这样
``` csharp
var generator=new ProxyGenerator();
var proxy = generator.CreateClassProxy(typeof(SampleService), new Interceptor());
```
![Alt text](image-1.png)
假设 SampleService 有参数构造函数
```csharp
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());
```
细心的朋友可能发现这时候我们引入了一个变量 而我们并未定义,
这时候我们添加如下代码:
```csharp
var services=new ServiceCollection();
services.AddLogging();//此处添加日志服务 伪代码 以便获取ILogger<SampleService>
services.AddSingleton<ProxyGenerator>(sp=>new ProxyGenerator());
servies.TryAddTransient<SampleService>();
var sp=services.BuildServiceProvider();
```
#### 接口
使用以上代码示例,假设我们要对 _ISampleService_ 进行代理生成,那么我们就可以这样
```csharp
services.TryAddTransient<ISampleService, SampleService>();//注入阶段添加以下代码以便获取ISampleService
var generator=sp.GetRequiredService<ProxyGenerator>();
var proxy=generator.CreateInterfaceProxyWithoutTarget(typeof(ISampleService),new Interceptor());//因为没有传入 原始对象,所以依然要求我们是一个无参构造的实现 TODO:可自行验证
```
看下原始定义
![Alt text](image-3.png)
假设我们获取了 _ISampleService_的实例
```csharp
var sampleSvc=sp.GetRequiredService<ISampleService>();
var proxy = generator.CreateInterfaceProxyWithTarget(typeof(ISampleService),sampleSvc, new Interceptor());
```
![Alt text](image-4.png)
可以发现 接口代理 和具体类代理 基本相似
细心的可以注意到 _SampleService.ShowAsync_ 很反常的 加了个关键字 _**virtual**_,想知道为什么,这里我们借用 _Castle_ 的文档 https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-introduction.md 有兴趣的朋友可以自行查询
### 总结
说到这里 我们已经基本了解了 castle构建动态代理的基本方法,接下来我们来总结一下 代理对象的构建方法 先区分目标是类还是接口 类 的代理方法要求 关键字virtual 使用 _CreateClassProxy_ 无参构造可以 使用 _CreateClassProxy_,有参数比较复杂 可以先获取到原始对象,传入 _CreateClassProxyWithTarget_;
接口同 无原始对象 _CreateInterfaceProxyWithoutTarget_ 有原始对象 _CreateInterfaceProxyWithTarget_,代码太多有点枯燥,本文先到这边。
- DependencyInjection Extensions Microsoft Castle Coredependencyinjection extensions microsoft castle dependenyinjection extensions microsoft castle extensions microsoft logging core windows windowsservices extensions microsoft extensions microsoft wpf extensions microsoft框架logging 第三方extensions microsoft logging 文件configuration extensions microsoft microsoft power core asp dependencyinjection