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

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


一开始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. DLL注入之修改PE静态注入

    DLL注入之修改PE静态注入 0x00 前言 我们要注入的的力量功能是下载baidu首页数据.代码如下: #include "stdio.h" #include"stdi ...

  2. springBoot整合redis(作缓存)

    springBoot整合Redis 1,配置Redis配置类 package org.redislearn.configuration; import java.lang.reflect.Method ...

  3. Docker装的Oracle 11g没有HR用户怎么办?一个脚本解决问题!

    #0x0 问题描述 这个学期有一门Oracle的课,我图省事就直接拉了个docker镜像来做练习,一直倒也没啥问题,但是今天的作业需要用到HR这个模板用户. 然而我执行alter user hr ac ...

  4. 用svg实现一个环形进度条

    svg实现环形进度条需要用到的知识: 1.会使用path的d属性画一个圆环 //用svg的path元素的A命令画圆 <path d=" M cx cy m 0 -r a r r 0 1 ...

  5. javascript基础(七):js发送请求

    GET请求 $.get("/api/v1.0/user",function(resp){ // 用户未登录 if ("4101" == resp.errno) ...

  6. javascript基础(五): jQuery

     jQuery javaScript和jQuery的关系? jQuery库,里面存在大量的JavaScript函数 获取jQuery 公式:$(selector).action() <!DOCT ...

  7. bzoj4395[Usaco2015 dec]Switching on the Lights*

    bzoj4395[Usaco2015 dec]Switching on the Lights 题意: n*n个房间,奶牛初始在(1,1),且只能在亮的房间里活动.每当奶牛经过一个房间,就可以打开这个房 ...

  8. Python+selenium+unittest+HTMLTestReportCN单元测试框架分享

    分享一个比较基础的,系统性的知识点.Python+selenium+unittest+HTMLTestReportCN单元测试框架分享 Unittest简介 unittest是Python语言的单元测 ...

  9. P1050 精卫填海

    [问题描述] 发鸠之山,其上多柘木.有鸟焉,其状如乌,文首,白喙,赤足,名曰精卫,其名自詨.是炎帝之少女,名曰女娃.女娃游于东海,溺而不返,故为精卫.常衔西山之木石,以堙于东海.——<山海经&g ...

  10. 12C oracle 12.1.0.2版本打补丁

    从support  1454618.1文档 中可以下载到各版本的补丁和PSU. 此次采用的是28349311 版本号的psu 和28440711 版本号的jvm.opatch版本号6880880_12 ...