最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

.NET?Core基于EMIT編寫的輕量級AOP框架CZGL.AOP

 更新時間:2022年02月23日 09:32:48   作者:癡者工良  
這篇文章介紹了.NET?Core基于EMIT編寫的輕量級AOP框架CZGL.AOP,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

Nuget 庫地址:https://www.nuget.org/packages/CZGL.AOP/

Github 庫地址:https://github.com/whuanle/CZGL.AOP

CZGL.AOP 是 基于 EMIT 編寫的 一個簡單輕量的AOP框架,支持非侵入式代理,支持.NET Core/ASP.NET Core,以及支持多種依賴注入框架。

1,快速入門

CZGL.AOP 使用比較簡單,你只需要使用 [Interceptor] 特性標記需要代理的類型,然后使用繼承 ActionAttribute 的特性標記要被代理的方法或?qū)傩浴?/p>

1.1 繼承 ActionAttribute 特性

ActionAttribute 是用于代理方法或?qū)傩缘奶匦詷擞洠荒苤苯邮褂?,需要繼承后重寫方法。

示例如下:

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            Console.WriteLine("執(zhí)行前");
        }

        public override object After(AspectContext context)
        {
            Console.WriteLine("執(zhí)行后");
            if (context.IsMethod)
                return context.MethodResult;
            else if (context.IsProperty)
                return context.PropertyValue;
            return null;
        }
    }

Before 會在被代理的方法執(zhí)行前或被代理的屬性調(diào)用時生效,你可以通過 AspectContext 上下文,獲取、修改傳遞的參數(shù)。

After 在方法執(zhí)行后或?qū)傩哉{(diào)用時生效,你可以通過上下文獲取、修改返回值。

1.2 標記代理類型

在被代理的類型中,使用 [Interceptor] 特性來標記,在需要代理的方法中,使用 繼承了 ActionAttribute 的特性來標記。

此方法是侵入式的,需要在編譯前完成。

[Interceptor]
public class Test : ITest
{
    [Log] public virtual string A { get; set; }
    [Log]
    public virtual void MyMethod()
    {
        Console.WriteLine("運行中");
    }
}

注意的是,一個方法或?qū)傩灾荒茉O(shè)置一個攔截器。

2,如何創(chuàng)建代理類型

CZGL.AOP 有多種生成代理類型的方式,下面介紹簡單的方式。

請預(yù)先創(chuàng)建如下代碼:

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            Console.WriteLine("執(zhí)行前");
        }

        public override object After(AspectContext context)
        {
            Console.WriteLine("執(zhí)行后");
            if (context.IsMethod)
                return context.MethodResult;
            else if (context.IsProperty)
                return context.PropertyValue;
            return null;
        }
    }

    public interface ITest
    {
        void MyMethod();
    }

    [Interceptor]
    public class Test : ITest
    {
        [Log] public virtual string A { get; set; }
        public Test()
        {
            Console.WriteLine("構(gòu)造函數(shù)沒問題");
        }
        [Log]
        public virtual void MyMethod()
        {
            Console.WriteLine("運行中");
        }
    }

通過API直接創(chuàng)建

通過 CZGL.AOP 中的 AopInterceptor 類,你可以生成代理類型。

示例如下:

            ITest test1 = AopInterceptor.CreateProxyOfInterface<ITest, Test>();
            Test test2 = AopInterceptor.CreateProxyOfClass<Test>();
            test1.MyMethod();
            test2.MyMethod();

CreateProxyOfInterface 通過接口創(chuàng)建代理類型;CreateProxyOfClass 通過類創(chuàng)建代理類型;

默認調(diào)用的是無參構(gòu)造函數(shù)。

2,創(chuàng)建代理類型

通過API

你可以參考源碼解決方案

中的 ExampleConsole 項目。

如果要直接使用 AopInterceptor.CreateProxyOfInterface 和 AopInterceptor.CreateProxyOfClass 方法,通過接口或類來創(chuàng)建代理類型。

        ITest test1 = AopInterceptor.CreateProxyOfInterface<ITest, Test>();
        Test test2 = AopInterceptor.CreateProxyOfClass<Test>();

如果要指定實例化的構(gòu)造函數(shù),可以這樣:

            // 指定構(gòu)造函數(shù)
            test2 = AopInterceptor.CreateProxyOfClass<Test>("aaa", "bbb");
            test2.MyMethod();

通過 Microsoft.Extensions.DependencyInjection

Microsoft.Extensions.DependencyInjection 是 .NET Core/ASP.NET Core 默認的依賴注入容器。

如果需要支持 ASP.NET Core 中使用 AOP,你可以在 Nuget 包中安裝 CZGL.AOP.MEDI。

如果你在控制臺下使用 Microsoft.Extensions.DependencyInjection,你可以使用名為 BuildAopProxy 的 IServiceCollection 拓展方法來為容器中的類型,生成代理類型。

示例如下:

            IServiceCollection _services = new ServiceCollection();
            _services.AddTransient<ITest, Test>();
            var serviceProvider = _services.BuildAopProxy().BuildServiceProvider();
            serviceProvider.GetService<ITest>();
            return serviceProvider;

你可以參考源碼解決方案中的 ExampleMEDI 項目。

如果你要在 ASP.NET Core 中使用,你可以在 Startup 中,ConfigureServices 方法的最后一行代碼使用 services.BuildAopProxy(); 。

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.BuildAopProxy();
        }

還可以在 Program 的 IHostBuilder 中使用 .UseServiceProviderFactory(new AOPServiceProxviderFactory()) 來配置使用 CZGL.AOP。

示例:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new AOPServiceProxviderFactory())
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

可以參考解決方案中的 ExampleConsole 和 ExampleWebMEDI 兩個項目。

你不必擔(dān)心引入 CZGL.AOP 后,使用依賴注入會使程序變慢或者破壞容器中的原有屬性。CZGL.AOP 只會在創(chuàng)建容器時處理需要被代理的類型,不會影響容器中的服務(wù),也不會干擾到依賴注入的執(zhí)行。

通過 Autofac

如果需要在 Autofac 中使用 AOP,則需要引用 CZGL.AOP.Autofac 包。

如果你在控制臺程序中使用 Autofac,則可以在 Build() 后面使用 BuildAopProxy()。

            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterType<Test>().As<ITest>();
            var container = builder.Build().BuildAopProxy();

            using (ILifetimeScope scope = container.BeginLifetimeScope())
            {
                // 獲取實例
                ITest myService = scope.Resolve<ITest>();
                myService.MyMethod();
            }

            Console.ReadKey();
        }

要注意的是,在已經(jīng)完成的組件注冊創(chuàng)建一個新的容器后,才能調(diào)用 BuildAopProxy() 方法,

這樣針對一個新的容器你可以考慮是否需要對容器中的組件進行代理。

如果在 ASP.NET Core 中使用 Autofac,你需要在 Program 類的 IHostBuilder 中使用:

.UseServiceProviderFactory(new AutofacServiceProviderFactory())

如果需要代理已經(jīng)注冊的組件,則將其替換為:

 .UseServiceProviderFactory(new CZGL.AOP.Autofac.AOPServiceProxviderFactory())

請參考 源碼解決方案中的 ExampleAutofac 和 ExampleWebAutofac 兩個項目。

3,深入使用

代理類型

要被代理的類型,需要使用 [Interceptor]來標記,例如:

    [Interceptor]
    public class Test : ITest
    {
    }

支持泛型類型。

被代理的類型必須是可被繼承的。

類型的構(gòu)造函數(shù)沒有限制,你可以隨意編寫。

在使用 API 創(chuàng)建代理類型并且實例化時,你可以指定使用哪個構(gòu)造函數(shù)。

例如:

			string a="",b="",c="";
			ITest test1 = AopInterceptor.CreateProxyOfInterface<ITest, Test>(a,b,c);

API 會根據(jù)參數(shù)的多少以及參數(shù)的類型自動尋找合適的構(gòu)造函數(shù)。

方法、屬性代理

為了代理方法或?qū)傩?,你需要繼承 ActionAttribute 特性,然后為方法或?qū)傩詷擞洿颂匦?,并且將方法或?qū)傩栽O(shè)置為 virtual

一個類型中的不同方法,可以使用不同的攔截器。

        [Log1]
        public virtual void MyMethod1(){}
        
        [Log2]
        public virtual void MyMethod2(){}

對于屬性,可以在屬性上直接使用特性,或者只在 get 或 set 構(gòu)造器使用。

        [Log] public virtual string A { get; set; }
        
        // 或
        public virtual string A { [Log] get; set; }
        
        // 或
        public virtual string A { get; [Log] set; }

如果在屬性上使用特性,相當于 [Log] get; [Log] set;。

上下文

一個簡單的方法或?qū)傩詳r截標記是這樣的:

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            Console.WriteLine("執(zhí)行前");
        }

        public override object After(AspectContext context)
        {
            Console.WriteLine("執(zhí)行后");
            if (context.IsMethod)
                return context.MethodResult;
            else if (context.IsProperty)
                return context.PropertyValue;
            return null;
        }
    }

AspectContext 的屬性說明如下:

字段說明
Type當前被代理類型生成的代理類型
ConstructorParamters類型被實例化時使用的構(gòu)造函數(shù)的參數(shù),如果構(gòu)造函數(shù)沒有參數(shù),則 MethodValues.Length = 0,而不是 MethodValues 為 null。
IsProperty當前攔截的是屬性
PropertyInfo當前被執(zhí)行的屬性的信息,可為 null。
PropertyValue但調(diào)用的是屬性時,返回 get 的結(jié)果或 set 的 value 值。
IsMethod當前攔截的是方法
MethodInfo當前方法的信息
MethodValues方法被調(diào)用時傳遞的參數(shù),如果此方法沒有參數(shù),則 MethodValues.Length = 0,而不是 MethodValues 為 null
MethodResult方法執(zhí)行返回的結(jié)果(如果有)

攔截方法或?qū)傩缘膮?shù)

通過上下文,你可以修改方法或?qū)傩缘膮?shù)以及攔截返回結(jié)果:

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            // 攔截并修改方法的參數(shù)
            for (int i = 0; i < context.MethodValues.Length; i++)
            {
                context.MethodValues[i] = (int)context.MethodValues[i] + 1;
            }
            Console.WriteLine("執(zhí)行前");
        }

        public override object After(AspectContext context)
        {
            Console.WriteLine("執(zhí)行后");

            // 攔截方法的執(zhí)行結(jié)果
            context.MethodResult = (int)context.MethodResult + 664;

            if (context.IsMethod)
                return context.MethodResult;
            else if (context.IsProperty)
                return context.PropertyValue;
            return null;
        }
    }

    [Interceptor]
    public class Test
    {
        [Log]
        public virtual int Sum(int a, int b)
        {
            Console.WriteLine("運行中");
            return a + b;
        }
    }
            Test test = AopInterceptor.CreateProxyOfClass<Test>();

            Console.WriteLine(test.Sum(1, 1));

方法的參數(shù)支持 in、ref、out;支持泛型方法泛型屬性;支持異步方法;

非侵入式代理

此種方式不需要改動被代理的類型,你也可以代理程序集中的類型。

    public class LogAttribute : ActionAttribute
    {
        public override void Before(AspectContext context)
        {
            Console.WriteLine("執(zhí)行前");
        }

        public override object After(AspectContext context)
        {
            Console.WriteLine("執(zhí)行后");
            if (context.IsMethod)
                return context.MethodResult;
            else if (context.IsProperty)
                return context.PropertyValue;
            return null;
        }
    }
    public class TestNo
    {
        public virtual string A { get; set; }
        public virtual void MyMethod()
        {
            Console.WriteLine("運行中");
        }
    }
            TestNo test3 = AopInterceptor.CreateProxyOfType<TestNo>(new ProxyTypeBuilder()
                .AddProxyMethod(typeof(LogAttribute), typeof(TestNo).GetMethod(nameof(TestNo.MyMethod)))
                .AddProxyMethod(typeof(LogAttribute), typeof(TestNo).GetProperty(nameof(TestNo.A)).GetSetMethod()));

通過 ProxyTypeBuilder 來構(gòu)建代理類型。

代理方法或?qū)傩远际鞘褂?nbsp;AddProxyMethod,第一個參數(shù)是要使用的攔截器,第二個參數(shù)是要攔截的方法。

如果要攔截屬性,請分開設(shè)置屬性的 getset 構(gòu)造。

如果多個方法或?qū)傩允褂猛粋€攔截器,則可以這樣:

            TestNo test3 = AopInterceptor.CreateProxyOfType<TestNo>(
                new ProxyTypeBuilder(new Type[] { typeof(LogAttribute) })
                .AddProxyMethod("LogAttribute", typeof(TestNo).GetMethod(nameof(TestNo.MyMethod)))
                .AddProxyMethod("LogAttribute", typeof(TestNo).GetProperty(nameof(TestNo.A)).GetSetMethod()));
            TestNo test3 = AopInterceptor.CreateProxyOfType<TestNo>(
                new ProxyTypeBuilder(new Type[] { typeof(LogAttribute) })
                .AddProxyMethod("LogAttribute", typeof(TestNo).GetMethod(nameof(TestNo.MyMethod)))
                .AddProxyMethod(typeof(LogAttribute2), typeof(TestNo).GetProperty(nameof(TestNo.A)).GetSetMethod()));

在構(gòu)造函數(shù)中傳遞過去所需要的攔截器,然后在攔截時使用。

到此這篇關(guān)于.NET Core基于EMIT編寫的輕量級AOP框架CZGL.AOP的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論

瑞丽市| 洛扎县| 泊头市| 花垣县| 镇江市| 桓仁| 金秀| 浏阳市| 铜川市| 秭归县| 武陟县| 白玉县| 绵竹市| 玉屏| 织金县| 五河县| 随州市| 新平| 大港区| 龙岩市| 庆元县| 南昌市| 根河市| 盐山县| 仙桃市| 囊谦县| 沁源县| 荥经县| 横峰县| 孝昌县| 正镶白旗| 荃湾区| 京山县| 澜沧| 宾阳县| 杂多县| 泗阳县| 都兰县| 贺兰县| 灌阳县| 伊宁县|