首页 > 其他分享 >.net使用DispatchProxy

.net使用DispatchProxy

时间:2023-03-03 14:23:27浏览次数:45  
标签:obj string int void DispatchProxy 使用 net type public

实现动态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[i]));
                }
                MethodCallExpression method = Expression.Call(Expression.Constant(_this), targetMethod, listparame);
                Delegate? lambda = Expression.Lambda(method, listparame).Compile();
                dic.TryAdd(key, lambda);
            }
            obj= dic[key].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

 [AttributeUsage(AttributeTargets.Class)]
    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);
}
///这里是Intercept是实现类 [DynamicTypeAttribut(typeof(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();///创建
})

 

标签:obj,string,int,void,DispatchProxy,使用,net,type,public
From: https://www.cnblogs.com/bay-max-/p/17175481.html

相关文章

  • Telnet协议
    1.开启telnet协议控制面板--程序--程序和功能(启用与关闭程序)--启用Telnet客户端2.使用命令访问水木社区(久远年代的上网)水木社区 telnetbbs.newsmth.net 3.关停或......
  • ChatGpt聊天API使用
    昨天ChatGpt发布了聊天API,新增了两个模型,目前还是测试阶段gpt-3.5-turbo功能强大的GPT-3.5模型,专门针对聊天做了优化gpt-3.5-turbo-0301此模型只支持到今年6月份所......
  • delphi 使用TFlowPanel容器,实现对内含控件进行自动排版
    效果图:   需求:当用户新增或者删除控件时,后面的控件(如果有的话)自动后退或者前移实现:需要用的控件是TFlowPanel,临时演员是TscGPEdit1.TFlowPanel设置......
  • 如何在 JavaScript 中使用媒体查询
    前言说起媒体查询想必大家最先想到的都是CSS中@media,没错,这是我们最常用的媒体查询方法,主要用来为我们的网站做适配处理。比如:h1{font-size:2rem;color:green;......
  • C/C++ 数据结构使用数组实现队列的基本操作
    //使用数组实现队列#include<iostream>#include<Windows.h>usingnamespacestd;#defineMAXSIZE5//队列的最大容量typedefintDataType;//队列中的元素类型......
  • 实验一 C语言开发环境使用和数据类型、运算符、表达式
    实验任务一1-1程序源码//打印一个字符小人#include<stdio.h>intmain(){printf("o\n");printf("<H>\n");printf("II\n");return0;......
  • Android studio 使用小米手机(Redmi K30 Pro)真机调试
    Androidstudio虚拟机调试启动很慢,而且有些应用还必须要用手机调试,还得把apk发到手机上安装,比较麻烦。所以手机通过USB直接连接电脑在线调试,方便快捷。手边有一部小米的R......
  • 推荐一个开源的 .NET 二维码生成库
    推荐一个开源的.NET二维码生成库dotnet编程大全专注C#WPF编程,dotnet编程大全​关注他 2人赞同了该文章       你好,......
  • (个人使用)安静、舒缓钢琴曲
    作者:海岸之鱼链接:https://www.zhihu.com/question/23614380/answer/250980982来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。名气太大不......
  • 适用于 .NET 的开源文本差异对比组件
    适用于.NET的开源文本差异对比组件DotNet大王源码资料,微信zhaoxi965,有问必复​关注他 1人赞同了该文章对于开发人员来说,Git是我们经常使用......