aop切片编程实现 #
一、实现原理 #
- 注入真正实现类;
- 替换实现类,将自行实现的代理类注入,替换真正的实现类,代理类的Target为目标真正实现类;
- 在代理类中使用反射,执行真正的实现类。
二、使用场景 #
- 权限
- 缓存
- 内容传递
- 记录跟踪(如业务节点上报、日志等)
- 错误处理
......
三、例子 #
需要更新框架最新版
1、定义代理接口 #
public interface IDataReporting
{
}
2、定义代理实现 #
//TODO是需要自己加的业务
//可以利用Services获取已经注入的类,用来调用其他接口的方法,如var _service = Services.GetService<T>();
[SuppressSniffer]
public class DataReporting : AspectDispatchProxy, IDispatchProxy
{
/// <summary>
/// 被代理对象
/// </summary>
public object Target { get; set; }
/// <summary>
/// 服务提供器
/// </summary>
public IServiceProvider Services { get; set; }
/// <inheritdoc/>
public override object Invoke(MethodInfo method, object[] args)
{
//TODO
var result = method.Invoke(Target, args);
//TODO
return result;
}
/// <inheritdoc/>
public override Task InvokeAsync(MethodInfo method, object[] args)
{
//TODO
var result = (Task)method.Invoke(Target, args);
//TODO
return result;
}
/// <inheritdoc/>
public override Task<T> InvokeAsyncT<T>(MethodInfo method, object[] args)
{
//TODO
var result = (Task<T>)method.Invoke(Target, args);
//TODO
return result;
}
}
3、注入 #
1、本项目使用 #
//在程序入口(.net 6风格入口在Program.cs,其他在Startup.cs)添加代码
services.AddScopedDispatchProxyForInterface<DataReporting, IDataReporting>();
2、提供其他项目使用 #
//当然,这也可以本项目使用,不过要提供给其他项目使用,要注意依赖关系问题。 //添加扩展方法,如:
//当然,这也可以本项目使用,不过要提供给其他项目使用,要注意依赖关系问题。
//添加扩展方法,如:
public static class DataReportingCollectionExtensions
{
public static IServiceCollection AddDataReporting(this IServiceCollection services)
{
services.AddScopedDispatchProxyForInterface<DataReporting, IDataReporting>();
return services;
}
}
4、使用 #
4.1、接口 #
//需要实现代理接口(本案例的代理接口是IDataReporting)
public interface ITestProxyService : IDataReporting
{
Task Test1();
Task<string> Test2(string aaa);
void Test3();
string Test4();
}
4.2、实现类 #
//需要实现接口生命周期(本案例是ITransient)
public class TestProxyService : ITestProxyService , ITransient
{
public async Task Test1()
{
Console.WriteLine("Test1");
}
public async Task<string> Test2(string aaa)
{
Console.WriteLine("Test2");
return await Task.FromResult(aaa);
}
public void Test3()
{
Console.WriteLine("Test3");
}
public string Test4()
{
Console.WriteLine("Test4");
return "Test4";
}
}