dotnet core 2 使用 DispatchProxy 做動態代理 AOP 入門

本文簡單告訴大家如何在 .NET Core 裏面使用 AOP 切面編程,使用 DispatchProxy 做任意接口的動態代理實現

使用 DispatchProxy 有一些限制,如只能創建接口的實例。使用 DispatchProxy 可以讓咱做到從無中創建出某個實例,這個實例繼承咱想要的接口

首先需要創建某個動態代理類繼承 DispatchProxy 類,例如創建 Foo 類。此時需要實現 Invoke 接口,這個接口的含義是當代碼調用接口裏面的函數,包括屬性的設置和獲取函數的時候將會進入 Invoke 方法

        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            // 忽略代碼
        }

因此通過 Invoke 方法可以假裝自己是對應的接口的實現,可以進行隨意更改執行邏輯以及修改返回值

而 DispatchProxy 另一個核心方法是靜態的 Create 方法,這個方法要求傳入兩個泛形,第一個類型是想要創建出來的實例繼承的接口,第二個類型是某個繼承 DispatchProxy 的類

例如咱定義了一個 IF1 的接口,此時可以在 Foo 添加如下代碼創建出一個不存在的類型實例,這個實例繼承了 IF1 接口

    public class Foo : DispatchProxy
    {
        public static T GetObject<T>()
        {
            return DispatchProxy.Create<T, Foo>();
        }

        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            return "lindexi";
        }
    }

假設 IF1 的定義如下

    interface IF1
    {
        string F2();
    }

此時的使用方法如下

            Console.WriteLine(Foo.GetObject<IF1>().F2());

執行代碼可以看到輸出了 lindexi 也就是實際調用了 Foo 方法

可以看到 DispatchProxy 的作用就是提供靜態方法用於創建繼承指定接口的對象,同時讓繼承 DispatchProxy 的類可以拿到接口所調用的方法,用來修改執行邏輯和返回值

一個實際的使用的例子,提供了調用某個對象的每個方法之前給這個對象調用方法記日誌,這是最簡便的記日誌的方法了,儘管性能很渣

    public class LoggingAdvice<T> : DispatchProxy
    {
        private T Object { set; get; }


        public static T CreateLogging(Func<T> creator)
        {
            object proxy = DispatchProxy.Create<T, LoggingAdvice<T>>();
            ((LoggingAdvice<T>)proxy).Object = creator();
            return (T)proxy;
        }

        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            Console.WriteLine($"開始執行 {targetMethod.Name}");

            var result = targetMethod.Invoke(Object, args);

            Console.WriteLine($"執行完成 {targetMethod.Name}");

            return result;
        }
    }

此時就能做到在方法執行前後添加日誌,如這裏有一個接口和一個類,使用方法請參考以下示例

    class Program
    {
        static void Main(string[] args)
        {
            var foo = LoggingAdvice<IF1>.CreateLogging(() => new Foo());
            foo.F2();
        }
    }

    interface IF1
    {
        string F2();
    }

    class Foo : IF1
    {
        /// <inheritdoc />
        public string F2()
        {
            return "lindexi";
        }
    }

參考

在.NET Core中使用DispatchProxy“實現”非公開的接口 - LamondLu - 博客園

使用.net core中的類DispatchProxy實現AOP - 歐陽.NET - 博客園

我搭建了自己的博客 https://blog.lindexi.com/ 歡迎大家訪問,裏面有很多新的博客。只有在我看到博客寫成熟之後纔會放在csdn或博客園,但是一旦發佈了就不再更新

如果在博客看到有任何不懂的,歡迎交流,我搭建了 dotnet 職業技術學院 歡迎大家加入

如有不方便在博客評論的問題,可以加我 QQ 2844808902 交流

知識共享許可協議
本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名林德熙(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我聯繫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章