于今天,功能终于完善度到比较满意的程度了

准备好好写一篇文章,而不是之前的流水账,分享一下最近这些天的踩坑


一开始AOP选的微软提供的DispatchProxy

关于这个,有大佬的文章,可以看看,了解一下

https://www.cnblogs.com/ElderJames/p/implement-simple-Aop-using-a-dotnet-core-library-System-Reflection-DispatchProxy.html

初步完成后,发现几个大问题,异步不支持,不支持构造器注入,代理类必须是继承DispatchProxy的公开类

我就想到我偶像Lemon大佬的著作AspectCore了,依稀记得是Emit构建的代理类

也有代码可以参考学习,那就开干,前后四天多的时间,终于完工

下面介绍一下我的AOP组件 NCoreCoder.Aop的使用以及高级应用


简单的使用NCoreCoder.Aop

NCoreCoder.Aop支持依赖注入,用依赖注入的方式完成代理类和接口的关联

支持.Net Core 3.0以及以下的依赖注入方式

示例

    public interface IMyClass
{
void TestVoid();
int TestInt();
Task TestAsync();
Task<int> TestIntAsync();
} [JitInject]
internal class MyClass : IMyClass
{
public void TestVoid()
{
Console.WriteLine("TestVoid");
} public int TestInt()
{
Console.WriteLine("TestInt"); return ;
} public Task TestAsync()
{
Console.WriteLine("TestAsync"); return Task.CompletedTask;
} public Task<int> TestIntAsync()
{
Console.WriteLine("TestIntAsync"); return Task.FromResult();
}
}

打上JitInject特性是证明这个类需要实现代理

这里就只是构建代理类,没有方法并走代理流程,代理支持 同步API、异步无返回值API、异步有返回值API

要拦截的方法,默认是继承JitAopAttribute,打特性方式完成拦截器注入

打在继承的实现类上

比如

    [AttributeUsage(AttributeTargets.Method)]
internal class TestJitAttribute : JitAopAttribute
{
public override void Before(MethodReflector method, object instance, params object[] param)
{
} public override void After(MethodReflector method, object instance, params object[] param)
{
} public override Task BeforeAsync(MethodReflector method, object instance, params object[] param)
{return Task.CompletedTask;
} public override Task AfterAsync(MethodReflector method, object instance, params object[] param)
{return Task.CompletedTask;
}
}

在需要拦截的方法上,打上TestJit即可

        [TestJit]
public void TestVoid()
{
Console.WriteLine("TestVoid");
} public int TestInt()
{
Console.WriteLine("TestInt"); return ;
} public Task TestAsync()
{
Console.WriteLine("TestAsync"); return Task.CompletedTask;
} public Task<int> TestIntAsync()
{
Console.WriteLine("TestIntAsync"); return Task.FromResult();
}
}

这样TestVoid方法就要走AOP流程了

Asp.Net Core 3.0以下

因为Asp.Net Core 3.0以下的Startup.ConfigService方法支持直接修改返回值变成IServiceProvider

所以在Asp.Net Core 3.0以下,依赖注入都是在Startup.ConfigService里面修改IServiceProvider到自定义的IServiceProvider完成替换依赖注入容器和流程的效果,比如Autofac

        public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//略略略
}

改为

        public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//略略略
service.AddSingleton<IMyClass, MyClass>(); //修改Ioc容器流程
return service.BuilderJit();
}

Asp.Net Core 3.0

Asp.Net Core 3.0的替换依赖注入流程变了

无法再修改Startup.ConfigService返回值了,只要不是void,运行就抛出异常

查看的Program.CreateHostBuilder

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

改为

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

这里可以保持原有依赖注入,也可以增加一个方法

        public void ConfigureContainer(JitAopBuilder builder)
{
builder.Add<IMyClass, MyClass>(ServiceLifetime.Singleton);
}

测试Aop

            var service = new ServiceCollection();

            service.AddSingleton<IMyClass, MyClass>();

            var serviceProvider = service.BuilderJit();

            TypeBuilderFactory.Instance.Save();

            var myclass = serviceProvider.GetRequiredService<IMyClass>();

            Task.Factory.StartNew(async () =>
{
myclass.TestVoid();
var result1 = myclass.TestInt(); await myclass.TestAsync();
var result2 = await myclass.TestIntAsync();
}); Console.ReadLine();

我们运行看看myclass对象是什么~

不是原有的MyClass对象


高级扩展

我们现在如果要针对不同流程,而不是默认的Before->After

那么我们就需要自定义一个IAopActors了

我们默认的JitAopAttribute的流程就是一个默认DefaultAopActors

编写一个公开的类,继承自IAopActors

IAopActors接口如下

然后再接口上打上特性AopActorsAttribute

特性的构造参数是Type对应了自定义的AopActors的Type

    public class TestActors : IAopActors
{
public object Execute(AopContext context)
{
throw new NotImplementedException();
} public Task<TResult> ExecuteAsync<TResult>(AopContext context)
{
throw new NotImplementedException();
} public Task InvokeAsync(AopContext context)
{
throw new NotImplementedException();
}
}
    [AopActors(typeof(TestActors))]
public interface IMyClass
{
void TestVoid();
int TestInt();
Task TestAsync();
Task<int> TestIntAsync();
}

个人文笔不好,如有疑问,可以加“.Net应用程序框架交流” 群号386092459 欢迎到群里和我反馈Bug或者建议、交流Aop设计和Emit的知识

NCoreCoder.Aop详解的更多相关文章

  1. Spring4 AOP详解

    Spring4 AOP详解 第一章Spring 快速入门并没有对Spring4 的 AOP 做太多的描述,是因为AOP切面编程概念不好理解.所以这章主要从三个方面详解AOP:AOP简介(了解),基于注 ...

  2. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

  3. [Spring学习笔记 5 ] Spring AOP 详解1

    知识点回顾:一.IOC容器---DI依赖注入:setter注入(属性注入)/构造子注入/字段注入(注解 )/接口注入 out Spring IOC容器的使用: A.完全使用XML文件来配置容器所要管理 ...

  4. AOP 详解

    1. 需求:统计方法执行的性能情况(来源:<精通Spring 4.x>) // 性能监视类 PerformanceMonitor package com.noodles.proxy; pu ...

  5. Spring AOP详解(转载)所需要的包

    上一篇文章中,<Spring Aop详解(转载)>里的代码都可以运行,只是包比较多,中间缺少了几个相应的包,根据报错,几经百度搜索,终于补全了所有包. 截图如下: 在主测试类里面,有人怀疑 ...

  6. Spring AOP详解及简单应用

    Spring AOP详解   一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...

  7. 转:Spring AOP详解

    转:Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...

  8. Spring全家桶——SpringBoot之AOP详解

    Spring全家桶--SpringBoot之AOP详解 面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方 ...

  9. Spring Aop 详解二

    这是Spring Aop的第二篇,案例代码很详解,可以查看https://gitee.com/haimama/java-study/tree/master/spring-aop-demo. 阅读前,建 ...

随机推荐

  1. C# DataTable与Excel读取与导出

    /// <summary> /// Excel->DataTable /// </summary> /// <param name="filePath&q ...

  2. 深入学习JavaScript数据类型

    数据类型是我们学习JavaScript时最先接触的东西,它是JavaScript中最基础的知识,这些知识看似简单,但实则有着许多初学者甚至是部分学习了多年JavaScript的老手所不了解的知识. 数 ...

  3. Scala 基础(八):Scala 程序流程控制

    1.顺序控制 顺序控制介绍 程序从上到下逐行地执行,中间没有任何判断和跳转. 顺序控制举例和注意事项 Scala中定义变量时采用合法的前向引用.如: def main(args : Array[Str ...

  4. wtforms: remove ' fill out this field'

    As of WTForms 2.2 (June 2nd, 2018), fields now render the required attribute if they have a validato ...

  5. 数据可视化之DAX篇(十六)如何快速理解一个复杂的DAX?这个方法告诉你

    https://zhuanlan.zhihu.com/p/64422393 经常有朋友提出一个问题,然后我给出一个DAX之后,TA又不是很理解,反复多次沟通才能把一个表达式讲清楚.或者TA自己写了一个 ...

  6. DirectX11 With Windows SDK--33 曲面细分阶段(Tessellation)

    前言 曲面细分是Direct3D 11带来的其中一项重要的新功能.它引入了两个可编程着色器阶段以及一个固定的镶嵌处理过程.简单来说,曲面细分技术可以将几何体细分为更小的三角形,并以某种方式把这些新生成 ...

  7. hihoCoder 1039 字符消除 最详细的解题报告

    题目来源:字符消除 解题思路: 1.在给定字符串中的任意位置插入'A'.'B'.'C'中的任意一个字符,然后计算插入后的字符经过消除后最短的字符串长度: 2.在计算字符消除后最短长度时,智能一遍一遍的 ...

  8. golang | Go语言入门教程——结构体初始化与继承

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题第10篇文章,我们继续来看golang当中的面向对象部分. 在上一篇文章当中我们一起学习了怎么创建一个结构体,以及怎么 ...

  9. C#-性能-二维数组和数组的数组的性能比较

    两者是3:2的消耗比例 const int NUM = 10000; int[,] vec = new int[NUM, NUM]; Stopwatch sw = Stopwatch.StartNew ...

  10. MnasNet:经典轻量级神经网络搜索方法 | CVPR 2019

    论文提出了移动端的神经网络架构搜索方法,该方法主要有两个思路,首先使用多目标优化方法将模型在实际设备上的耗时融入搜索中,然后使用分解的层次搜索空间,来让网络保持层多样性的同时,搜索空间依然很简洁,能够 ...