聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(三)
聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(三)
1.聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(二)01-122.聊一聊如何结合Microsoft.Extensions.DependenyInjection和Castle.Core01-12
3.整合Microsoft.Extensions.DependencyInjection和Castle.Core(三)01-12
4.整合Microsoft.Extensions.DependencyInjection和Castle.Core(完结篇)01-13前言
今天的第三篇,感觉没啥人看呀,难道没有兄弟跟我有同样的整合需求吗???手动
,
本文会简短一些,介绍下 CastleCore 作为代理库的一些缺点甚至是硬伤
异步支持
先上代码
/// <summary>
/// 异常捕获、日志记录和耗时监控 拦截器 2024-1-12 21:28:22
/// </summary>
public class CatchLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
//TODO:类注释所写的逻辑
Console.WriteLine("Interceptor starting...");
invocation.Proceed();
Console.WriteLine("Interceptor ended...");
}
}
如上是一个最简单的 CastleCore 拦截器示例,为了该拦截器能在使用的时候可以直接标注在方法上使用,为我们做如下改动:
/// <summary>
/// 异常捕获、日志记录和耗时监控 拦截器 2024-1-12 21:28:22
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CatchLoggingInterceptor : Attribute, IInterceptor
{
public void Intercept(IInvocation invocation)
{
//TODO:类注释所写的逻辑
Console.WriteLine("Interceptor starting...");
invocation.Proceed();
Console.WriteLine("Interceptor ended...");
}
}
public class SampleService : ISampleService
{
[CatchLoggingInterceptor]
public virtual Task<string> ShowAsync()
{
Console.WriteLine(nameof(ShowAsync));
return Task.FromResult(nameof(ShowAsync));
}
}
public interface ISampleService
{
[CatchLoggingInterceptor]
Task<string> ShowAsync();
}
使用代码如下
public static async Task Main(string[] args)
{
var services = new ServiceCollection();
services.AddLogging();//此处添加日志服务 伪代码 以便获取ILogger<SampleService>
services.TryAddSingleton(sp => new ProxyGenerator());
services.TryAddTransient<SampleService>();
services.TryAddTransient<ISampleService, SampleService>();
var sp = services.BuildServiceProvider();
var generator = sp.GetRequiredService<ProxyGenerator>();
var instance = sp.GetRequiredService<SampleService>();
var proxy = generator.CreateClassProxyWithTarget(typeof(SampleService), instance, new CatchLoggingInterceptor()) as SampleService;
var name = await proxy.ShowAsync();
}
输入如图所示:
name也可以正常取到值,没问题
看下拦截器的定义 ,我们全部是同步方法,要知道dotnetcore下是推荐所有方法都是异步的, 我们对拦截器做如下改造:
public void Intercept(IInvocation invocation)
{
invocation.ReturnValue = IntercetpAsync(invocation);
}
private async Task IntercetpAsync(IInvocation invocation)
{
//TODO:类注释所写的逻辑
await Console.Out.WriteLineAsync("Interceptor starting...");
Console.WriteLine("Interceptor starting...");
invocation.Proceed();
await Console.Out.WriteLineAsync("Interceptor ended...");
}
如上,拦截器里面使用Console.Out执行了异步方法的拦截,再执行
此时引出 Castle代理的致命的问题:拦截方法默认无法异步
针对此问题,官方也已显式标明,并提供了具体的解决办法
https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-async-interception.md
这里我推荐 https://www.nuget.org/packages/stakx.DynamicProxy.AsyncInterceptor 的处理办法
其他缺点
- 拦截器内如何可以使用ioc的生态获取已经有的各项功能服务
- 某些场景下拦截器是需要传入常量 比方说,操作日志拦截,方法1 可能需要 Name="方法1",而方法二额需要 Name="方法2"
综上
上面三个缺点都是CastleCore 的硬伤,我们都要克服,后文会陆续解决这些问题,请各位看官拭目以待。写文很累,各位能不能dian点个star呢?您的鼓励会让我信心倍增,更新更快。
本文示例代码已上传至 https://gitee.com/gainorloss_259/microsoft-castle.git
漫思