zl程序教程

您现在的位置是:首页 >  后端

当前栏目

MSBuild + MSILInect实现编译时AOP-改变前后对比

AOP 实现 编译 对比 改变 前后
2023-09-14 09:00:58 时间

    实现静态AOP,就需要我们在预编译时期,修改IL实现对代码逻辑的修改。Mono.Cecil就是一个很好的IL解析和注入框架,参见编译时MSIL注入--实践Mono Cecil(1)

  我的思路为:在编译时将加有继承制MethodInterceptBaseAttribute标签的原方法,重新组装成一个方法(并加上[CompilerGenerated]标签),在加入横切注入接口前后代码,调用此方法。

比如代码:

复制代码 [TestAOPAttribute(Order = 1)]

public Class1 TestMethod1(int i, int j, Class1 c) 
        { 
            Console.WriteLine("ok"); 
            return new Class1(); 
        }

public class TestAOPAttribute : Green.AOP.MethodInterceptBase 
    { 

        #region IMethodInject Members 

        public override bool Executeing(Green.AOP.MethodExecutionEventArgs args) 
        { 
            Console.WriteLine(this.GetType() + ":" + "Executeing"); 
            return true; 
        } 

        public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args) 
        { 
            Console.WriteLine(this.GetType() + ":" + "Exceptioned"); 
            return Green.AOP.ExceptionStrategy.Handle; 
        } 

        public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args) 
        { 
            Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess"); 
        } 

        #endregion 

        #region IMethodInject Members 

               #endregion 
    } 复制代码

将会转化(实际注入IL,这里反编译为了c#代码,更清晰)为:

12

 

image

 

从这里你就会清晰的明白这里实现静态注入了机制和原理了。我们需要做的目的就是从IL出发改变原来代码逻辑,注入我们的截取代码。使用Mono.Cecil具体代码在程序包MethodILInjectTask中。

MatchedMethodInterceptBase是应用于class上匹配该class多个methodattribute基类。rule为匹配规则。

[TestAOP2Attribute(Rule = "TestMethod1*")]

public class Class1 


   image

这里需要对于继承制该基类的标示class的所有满足rule的方法进行注入。

PropertyInterceptBase:属性注入,Action属性标识get,set方法。

复制代码 [TestAOPPropertyGetAttribute(Action = PropertyInterceptAction.Get)] 
       public int TestProperty 
       { 
           get; 
           set; 
       } 复制代码

 

image

属性注入找出标示property,更具action选择get,set方法注入IL逻辑。

现在对于方法中获取attribute通过反射,性能存在一定问题。完全可以在class中注入属性,延时加载,Dictionary类级缓存来减少这方面损失,还暂时没考虑加入。

    不是很会写blog,所以有什么不明白的可留言,上一篇MSBuild + MSILInect实现编译时AOP之预览,由于时间写的没头没尾的,估计大家都看的很迷茫,迷茫该怎么写。关于IL注入Mono.Cecil可以参见编译时MSIL注入--实践Mono Cecil(1)和官方http://www.mono-project.com/Cecil。还有必须对MSIL具有一定了解(相同与Emit的IL注入)

   附带:源码下载


使用基于Roslyn的编译时AOP框架 介绍如何通过使用基于Roslyn的编译时AOP框架来解决.NET项目的代码复用问题。 可以在项目编译时自动插入指定代码,从而避免在运行时带来的性能消耗。
visual studio编写C#代码时“未能从程序集.....中加载类型”和“找不到方法”的一种可能的解决办法 编译前报错:$exception   { 未能从程序集 XSW.MySQLDAL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 中加载类型 XSW.MySQLDAL.EnterpriseLibraryProductDAL 。