翼度科技»论坛 编程开发 .net 查看内容

.net使用DispatchProxy

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
实现动态aop并注入 用表达式树调用目标方法
创建一个DynamicDispatchProxy类继承DispatchProxy,字典key最好是由路劲名称+方法参数组成 
  1. public class DynamicDispatchProxy<T> : DispatchProxy
  2. {
  3.     /// <summary>
  4.     /// 目标类
  5.     /// </summary>
  6.     private T _this { get; set; }
  7.     /// <summary>
  8.     /// 进入前方法
  9.     /// </summary>
  10.     private Action<string> _last { get; set; }
  11.     /// <summary>
  12.     /// 退出后方法
  13.     /// </summary>
  14.     private Action<string, object?> _next { get; set; }
  15.     private void last(string _v)
  16.     {
  17.         try
  18.         {
  19.             _last.Invoke(_v);
  20.         }
  21.         catch (System.Exception)
  22.         {
  23.         }
  24.     }
  25.     private void next(string _v, object _v1)
  26.     {
  27.         try
  28.         {
  29.             _next.Invoke(_v, _v1);
  30.         }
  31.         catch (System.Exception)
  32.         {
  33.         }
  34.     }
  35.     private static ConcurrentDictionary<string, Delegate?> dic = new ConcurrentDictionary<string, Delegate?>();
  36.     protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
  37.     {
  38.         last(targetMethod.Name);
  39.         object obj = null;
  40.         try
  41.         {
  42.             var paramstype = targetMethod.GetParameters().Select(d => d.ParameterType).ToList();
  43.             var key =typeof(T).FullName+ targetMethod.Name + string.Join(' ', paramstype.Select(d => d.Name));
  44.             if (!dic.ContainsKey(key))
  45.             {
  46.                 List<ParameterExpression> listparame = new List<ParameterExpression>();
  47.                 for (int i = 0; i < paramstype.Count; i++)
  48.                 {
  49.                     listparame.Add(Expression.Parameter(paramstype[i]));
  50.                 }
  51.                 MethodCallExpression method = Expression.Call(Expression.Constant(_this), targetMethod, listparame);
  52.                 Delegate? lambda = Expression.Lambda(method, listparame).Compile();
  53.                 dic.TryAdd(key, lambda);
  54.             }
  55.             obj= dic[key].DynamicInvoke(args);
  56.              next(targetMethod.Name,obj);
  57.             return obj;
  58.         }
  59.         catch (System.Exception ex)
  60.         {
  61.             throw ex;
  62.         }
  63.     }
  64.     public T Create(){
  65.         ///BuildServiceProvider 获取方法
  66.         var imp = IServiceCollectionHelp.GetService<T>();
  67.         ///拦截实现类的type
  68.         var attributtype = imp.GetType().GetCustomAttribute<DynamicTypeAttribut>();
  69.         ///在这之前要先注入 拦截实现类才能获取 Impintercept这是接口定义拦截前和拦截后
  70.         var Impintercept = IServiceCollectionHelp.GetService<IIntercept>(attributtype.type);
  71.         object o = Create<T, DynamicDispatchProxy<T>>();
  72.         DynamicDispatchProxy<T> pro=(DynamicDispatchProxy<T>)o;
  73.         ///赋值给上面委托
  74.         pro._this = imp;
  75.         pro._last = Impintercept.Last;
  76.         pro._next = Impintercept.Next;
  77.         return (T)o;
  78.     }
  79. }
复制代码
创建一个特性类 来获取拦截实现类的type !DynamicTypeAttribut
  1. [AttributeUsage(AttributeTargets.Class)]
  2.     public class DynamicTypeAttribut:Attribute
  3.     {
  4.         public Type type;
  5.         public DynamicTypeAttribut(Type type){
  6.             this.type=type;
  7.         }
  8.     }
复制代码
定义拦截接口 IIntercept
  1.   public interface IIntercept
  2.     {
  3.         void Last(string name);
  4.         void Next(string name,object? obj);
  5.     }
复制代码
拦截的目标
  1. public interface ITest
  2. {
  3.     void Write();
  4.     int Add(int v1,int v2);
  5. }<br>///这里是Intercept是实现类
  6. [DynamicTypeAttribut(typeof(Intercept))]
  7. public class Test : ITest
  8. {
  9.     public int Add(int v1, int v2)
  10.     {
  11.         Console.WriteLine(nameof(Add));
  12.        return v1+v2;
  13.     }
  14.     public void Write()
  15.     {
  16.       
  17.         Console.WriteLine(this.GetHashCode());
  18.     }
  19. }
复制代码
拦截方法的实现
  1. public class Intercept : IIntercept
  2. {
  3.     public void Last(string name)
  4.     {
  5.         Console.WriteLine(this.GetHashCode());
  6.         Console.WriteLine("进入"+name);
  7.     }
  8.     public void Next(string name, object? obj)
  9.     {
  10.         Console.WriteLine("推出"+name);
  11.         if( obj !=null)
  12.             Console.WriteLine("返回值"+obj);
  13.     }
  14. }
复制代码
注入
  1. ///注入拦截实现类 不然获取不到
  2. builder.Services.AddScoped< Intercept>();
  3. ///这里也要注入一次  不然也获取不到
  4. builder.Services.AddScoped<ITest, Test>();
  5. var _ = new DynamicDispatchProxy<ITest>();
  6. IServiceCollectionHelp.serviceProvider = builder.Services.BuildServiceProvider();
  7. builder.Services.AddScoped(typeof(ITest), d => {
  8.         return _.Create();///创建
  9. })
复制代码
 

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

举报 回复 使用道具