.net使用DispatchProxy

来源:https://www.cnblogs.com/bay-max-/archive/2023/03/03/17175481.html
-Advertisement-
Play Games

實現動態aop並註入 創建一個DynamicDispatchProxy類繼承DispatchProxy, public class DynamicDispatchProxy<T> : DispatchProxy { /// <summary> /// 目標類 /// </summary> priva ...


實現動態aop並註入 

創建一個DynamicDispatchProxy類繼承DispatchProxy,

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);
        */
      
obj= targetMethod.Invoke(_this,args);
      next("",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();///創建
})

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Vue 3 備忘清單 Vue 3漸進式 JavaScript 框架 Vue 3 備忘清單的快速參考列表,包含常用 API 和示例入門,為開發人員分享快速參考備忘單。 開發速查表大綱 入門 介紹 創建應用 應用實例 通過 CDN 使用 Vue 使用 ES 模塊構建版本 模板語法 文本插值 原始 HTM ...
  • 前言 TCP三次握手和四次揮手是面試題的熱門考點,它們分別對應TCP的連接和釋放過程 1.TCP通信包含那幾步? TCP通信過程包括三個步驟:建立TCP連接通道,傳輸數據,斷開TCP連接通道 上圖主要包括三部分:*建立連接、傳輸數據、斷開連接。* 建立TCP連接很簡單,通過三次握手便可建立連接。 建 ...
  • 1.單線程 單線程:只有一個線程,即CPU只執行一個任務(一個線程) 1 class Hero{ 2 String name; 3 Hero(String name){ 4 this.name = name; 5 } 6 public void show(){ 7 System.out.printl ...
  • #使用引用 #include <iostream> using namespace std; struct Time{ int h; int m; int s; }; void timeCompute(Time &t, int sec){ //引用作為形參 t.m = t.m + (t.s + se ...
  • Problem description unsigned char key[16] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; unsigned ...
  • 日常開發中,基於 Redis 天然支持分散式鎖,大家線上上分散式項目中都使用過 Redis 鎖。本文主要針對日常開發中加鎖過程中某些異常場景進行講解與分析。本文講解示例代碼都在 https://github.com/wayn111/newbee-mall-pro 項目 test 目錄下 RedisL ...
  • 程式代碼到可執行程式編譯鏈接過程 預編譯 以c++/c 語言為例,預編譯階段的工作有以下幾點: 處理所有#define 及條件預編譯指令(如 #if,#ifdef.....),並展開所有巨集定義。 刪除所有註釋("//" ,"/**/")。 處理 "#include",將被包含文件插入該預編譯指令位置 ...
  • 什麼是OpenAI https://openai.com OpenAI是一家人工智慧公司,成立於2015年,總部位於美國舊金山。該公司的使命是研究和開發能夠產生廣泛影響的人工智慧技術,並將這些技術傳播到整個社會。OpenAI由一些著名的科學家和企業家共同創立,包括伊隆·馬斯克、Sam Altman等 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...