群山春晓 发表于 2023-3-3 16:07:35

.net使用DispatchProxy

实现动态aop并注入 用表达式树调用目标方法
创建一个DynamicDispatchProxy类继承DispatchProxy,字典key最好是由路劲名称+方法参数组成 
public class DynamicDispatchProxy<T> : DispatchProxy
{
    /// <summary>
    /// 目标类
    /// </summary>
    private T _this { get; set; }
    /// <summary>
    /// 进入前方法
    /// </summary>
    private Action<string> _last { get; set; }
    /// <summary>
    /// 退出后方法
    /// </summary>
    private Action<string, object?> _next { get; set; }
    private void last(string _v)
    {
      try
      {
            _last.Invoke(_v);
      }
      catch (System.Exception)
      {

      }
    }
    private void next(string _v, object _v1)
    {
      try
      {
            _next.Invoke(_v, _v1);
      }
      catch (System.Exception)
      {

      }
    }
    private static ConcurrentDictionary<string, Delegate?> dic = new ConcurrentDictionary<string, Delegate?>();
    protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
    {
      last(targetMethod.Name);
      object obj = null;
      try
      {
            var paramstype = targetMethod.GetParameters().Select(d => d.ParameterType).ToList();
            var key =typeof(T).FullName+ targetMethod.Name + string.Join(' ', paramstype.Select(d => d.Name));
            if (!dic.ContainsKey(key))
            {
                List<ParameterExpression> listparame = new List<ParameterExpression>();
                for (int i = 0; i < paramstype.Count; i++)
                {
                  listparame.Add(Expression.Parameter(paramstype));
                }
                MethodCallExpression method = Expression.Call(Expression.Constant(_this), targetMethod, listparame);
                Delegate? lambda = Expression.Lambda(method, listparame).Compile();
                dic.TryAdd(key, lambda);
            }
            obj= dic.DynamicInvoke(args);
             next(targetMethod.Name,obj);
            return obj;
      }
      catch (System.Exception ex)
      {

            throw ex;
      }
    }
    public T Create(){
      ///BuildServiceProvider 获取方法
      var imp = IServiceCollectionHelp.GetService<T>();
      ///拦截实现类的type
      var attributtype = imp.GetType().GetCustomAttribute<DynamicTypeAttribut>();
      ///在这之前要先注入 拦截实现类才能获取 Impintercept这是接口定义拦截前和拦截后
      var Impintercept = IServiceCollectionHelp.GetService<IIntercept>(attributtype.type);
      object o = Create<T, DynamicDispatchProxy<T>>();
      DynamicDispatchProxy<T> pro=(DynamicDispatchProxy<T>)o;
      ///赋值给上面委托
      pro._this = imp;
      pro._last = Impintercept.Last;
      pro._next = Impintercept.Next;
      return (T)o;
    }
}创建一个特性类 来获取拦截实现类的type !DynamicTypeAttribut

    public class DynamicTypeAttribut:Attribute
    {
      public Type type;
      public DynamicTypeAttribut(Type type){
            this.type=type;
      }
    }定义拦截接口 IIntercept
public interface IIntercept
    {
      void Last(string name);
      void Next(string name,object? obj);
    }拦截的目标
public interface ITest
{
    void Write();
    int Add(int v1,int v2);
}<br>///这里是Intercept是实现类

public class Test : ITest
{
    public int Add(int v1, int v2)
    {
      Console.WriteLine(nameof(Add));
       return v1+v2;
    }

    public void Write()
    {
      
      Console.WriteLine(this.GetHashCode());
    }
}拦截方法的实现
public class Intercept : IIntercept
{
    public void Last(string name)
    {
      Console.WriteLine(this.GetHashCode());

      Console.WriteLine("进入"+name);
    }

    public void Next(string name, object? obj)
    {
      Console.WriteLine("推出"+name);
      if( obj !=null)
            Console.WriteLine("返回值"+obj);
    }
}注入
///注入拦截实现类 不然获取不到
builder.Services.AddScoped< Intercept>();
///这里也要注入一次不然也获取不到
builder.Services.AddScoped<ITest, Test>();
var _ = new DynamicDispatchProxy<ITest>();
IServiceCollectionHelp.serviceProvider = builder.Services.BuildServiceProvider();
builder.Services.AddScoped(typeof(ITest), d => {
      return _.Create();///创建
}) 

来源:https://www.cnblogs.com/bay-max-/archive/2023/03/03/17175481.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: .net使用DispatchProxy