MSBuild + MSILInect实现编译时AOP之预览

      在本文之前的前几篇浅谈.NET编译时注入(C#-->IL)浅谈VS编译自定义编译任务—MSBuild Task(csproject)编译时MSIL注入--实践Mono Cecil(1)已经讨论了MSBuild和Mono.Cicel。在这里我们将会利用它来实现一个简单的编译时AOP注入机制(这里所说的编译时是指c#到MSIL的预编译过程)。我更倾向于像EL(微软企业库框架)这类动态AOP。编译时AOP有PostSharp这种被称之为静态AOP框架,其优势在于直接代码语句,性能更好,它不需要我们多余的代码,像EL这种动态AOP,一般我们是不能直接new一个对象,需要容器(Container),在一些你的框架应用种,有时就需要使用者了解,再入我们对于WinForm、WebForm等.net平台上主流的基于微软事件机制的框架,事件方法的截获,往往我们需要改变、包装。在这时静态AOP就显出了他的优势。

Class Diagram:

1:IMethodInject:Interface,拥有Executeing,Exceptioned,ExecuteSuccess三个契约为别为执行前,异常,成功。它们都有公同的参数类型:MethodExecutionEventArgs

 

    Executeing:返回值为bool类型,将决定是否继续执行方法体。Exceptioned:属性Eeption代表发生的异常信息,返回值ExceptionStrategy(取值:Handle, ReThrow, ThrowNew)决定异常处理机制,Handle已处理并忽略,ReThrow重新抛出,ThrowNew抛出一个包装后的来源于MethodExecutionEventArgs 的Exception。ExecuteSuccess,对于拥有返回值的方法,可以修改MethodExecutionEventArgs 的ReturnValue,修改返回值。最后MethodExecutionEventArgs的Order决定多个Attribute的注入先后,即方法截获的先后顺序。

1:MethodInterceptBase:针对于方法Attribute标签,实现方法截获

[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    public class MethodInterceptBase : Attribute, IMethodInject
    {
        public int Order
        {
            get;
            set;
        }
        #region IMethodInject Members

        public virtual bool Executeing(MethodExecutionEventArgs args)
        {
            return true;
        }

        public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)
        {
            return ExceptionStrategy.ReThrow;
        }

        public virtual void ExecuteSuccess(MethodExecutionEventArgs args)
        {

        }
       
        #endregion
}

2:MatchedMethodInterceptBase:和上面方法之上的MethodInterceptBase大体一致,区别在于其应用于class之上,属性Rule为截获方法匹配(应用于多个方法之上相同截获),支持*匹配。

 

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]

    public class MatchedMethodInterceptBase : Attribute, IMethodInject

    {

        public int Order

        {

            get;

            set;

        }

 

        public string Rule

        {

            get;

            set;

        }

        #region IMethodInject Members

        public virtual bool Executeing(MethodExecutionEventArgs args)

        {

            return true;

        }
 

        public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)

        {

            return ExceptionStrategy.ReThrow;

        }

 

        public virtual void ExecuteSuccess(MethodExecutionEventArgs args)

        {

 

        }

       

        #endregion

    }

3:PropertyInterceptBase:实现属性的注入,其属性Action(enum PropertyInterceptAction:None Get, Set)指注入属性的get或者Set; 

 

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public class PropertyInterceptBase : Attribute, IMethodInject
    {
        public PropertyInterceptAction Action
        {
            get;
            set;
        }

        public int Order
        {
            get;
            set;
        }
        #region IMethodInject Members

        public virtual bool Executeing(MethodExecutionEventArgs args)
        {
            return true;
        }

        public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)
        {
            return ExceptionStrategy.ReThrow;
        }

        public virtual void ExecuteSuccess(MethodExecutionEventArgs args)
        {

        }

        #endregion
    }

其上默认都是Executeing继续执行,Exceptioned为抛出不处理,成功不修改result。

下面是一个简单测试Code:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Reflection;

using Green.AOP;

 

namespace Test

{   

    // [TestAOP2Attribute(Rule = "TestMethod1*")]

    public class Class1

    {

        // [TestAOPPropertyAttribute(Action = PropertyInterceptAction.Set)]

        [TestAOPPropertyGetAttribute(Action = PropertyInterceptAction.Get)]

        public testStrust TestProperty

        {

            get;

            set;

        }

        [Obsolete()]

        public static void Main(string[] args)

        {          

            try

            {

                var y = new Class1();

                // y.TestProperty = DateTime.Now;

                Console.WriteLine(y.TestProperty);

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex.ToString());

            }

            // new Class1().TestMethod1(1, 2, null);

            Console.Read();

            //throw new Exception("exfffffffffffffffffffff");

        }

        //[TestAOPAttribute(Order=1)]

        //[TestAOP1Attribute(TestProperty = 1, Template = "sdsdsd",Order=0)]

        public Class1 TestMethod1(int i, int j, Class1 c)

        {

            Console.WriteLine("ok");

            return new Class1();

        }

    }

    public class TestAOPPropertyGetAttribute : Green.AOP.PropertyInterceptBase

    {

        #region IMethodInject Members

        public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)

        {

            Console.WriteLine("------------------" + args);

            Console.WriteLine(args.Instance);

            Console.WriteLine(args.Method);

            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.ReThrow;

        }

        public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)

        {

            Console.WriteLine("-----------");

            Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess" + "--result:" + args.ReturnValue);

        }

        #endregion

    }

    public class TestAOPPropertyAttribute : Green.AOP.PropertyInterceptBase

    {

        #region IMethodInject Members

        public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)

        {

            Console.WriteLine(args.Instance);

            Console.WriteLine(args.Method);

            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

    }

    public class TestAOP2Attribute : Green.AOP.MatchedMethodInterceptBase

    {

        #region IMethodInject Members

        public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)

        {

            Console.WriteLine(args.Instance);

            Console.WriteLine(args.Method);

            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

        public bool Match(System.Reflection.MethodBase method)

        {

            return true;

        }

        #endregion

    }

 

    //[AttributeUsage(AttributeTargets.Method)]

    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

 

 

        public bool Match(System.Reflection.MethodBase method)

        {

            return true;

        }

 

        #endregion

    }

 

    [AttributeUsage(AttributeTargets.Method)]

    public class TestAOP1Attribute : Attribute, Green.AOP.IMethodInject

    {

        public int Order

        {

            get;

            set;

        }

 

        public int TestProperty

        {

            get;

            set;

        }

 

        public string Template

        {

            get;

            set;

        }

 

        #region IMethodInject Members

 

        public bool Executeing(Green.AOP.MethodExecutionEventArgs args)

        {

            Console.WriteLine(this.GetType() + ":" + "Executeing");

            return true;

        }

 

        public Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)

        {

            Console.WriteLine(this.GetType() + ":" + "Exceptioned");

            return Green.AOP.ExceptionStrategy.Handle;

        }

 

        public void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)

        {

            Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");

        }

 

        #endregion

 

        #region IMethodInject Members

 

 

        public bool Match(System.Reflection.MethodBase method)

        {

            return true;

        }

 

        #endregion

    }

 

}

 注意测试有两种方式(由于没有安装包):

1:先重编译测试项目,运行ConsoleApplication2(在属性中修改控制台其实参数)。在查看测试项目。

2:将项目ConsoleApplication2修改为类库,在添加修改csprojec信息,Task位于Green.AOP.MyBuildTask,具体可以参见上一篇浅谈VS编译自定义编译任务—MSBuild Task(csproject)

在后续将会从简单Demo分析实现原理。

 

作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/archive/2011/08/09/2132217.html

时间: 2024-10-30 08:42:30

MSBuild + MSILInect实现编译时AOP之预览的相关文章

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

    实现静态AOP,就需要我们在预编译时期,修改IL实现对代码逻辑的修改.Mono.Cecil就是一个很好的IL解析和注入框架,参见编译时MSIL注入--实践Mono Cecil(1).   我的思路为:在编译时将加有继承制MethodInterceptBaseAttribute标签的原方法,重新组装成一个方法(并加上[CompilerGenerated]标签),在加入横切注入接口前后代码,调用此方法. 比如代码: [TestAOPAttribute(Order = 1)] public C

Windows 10技术预览版安装怎么设置?

知识点分析: 熟悉Windows 10技术预览版的首次启动设置及账户注册界面. 操作步骤: 系统在首次完成启动后,进入设置界面: 建议使用快速设置,可直接进入登录界面: 设置登录账户,若没有账户,可左下角点创建一个新账户: 若用使用本地用户登录,可点击不使用Mcrosoft账户登录,如图: 完成设置. 出现安装更新的提示: 完成后,进入传统桌面: 恢复了的开始菜单. 补充:安装Windows 10技术预览版的系统要求 系统要求 基本上,如果您的电脑可以运行 Windows 8.1,则可以放心开始

C# tablelayoutpanel打印和预览问题

问题描述 根据需要做了一个tablelayoutpanel(好像只有这个控件能做表格,自已画除外),使用一切正常,但在最后时做打印预览和打印时,进行不下去了请问各位,如何才能打印出来tablelayoutpanel,最好有详细的代码. 解决方案 解决方案二:up解决方案三:再请帮助解决方案四:该回复于2013-02-25 14:35:28被版主删除

jquery入门—数据删除与隔行变色以及图片预览_jquery

1.功能需求:表格中数据隔行变色.删除数据.全选删除.鼠标移动到图片时显示图片预览 2.示例代码如下: 复制代码 代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> 数据管理 </TITLE> <META NAME="Generator" CONTENT="Edi

基于jquery实现图片上传本地预览功能_jquery

当我们在上传文件时如果每次都要上传到服务器才可以预览这个做看上合理其实是不合理的,如果网速慢或图片有问题,这样不但浪费客户时间同时也浪费服务器资源了,下面我们介绍利用js上传图片时本地实现预览,希望此方法对各位有所帮助哦.一.原理 分为两步: 当上传图片的input被触发并选择本地图片之后获取要上传的图片这个对象的URL(对象URL): 把对象URL赋值给事先写好的img标签的src属性即可把图片显示出来. 在这里,我们需要了解Javascript里File对象.Blob对象和window.UR

asp.net winFrom 自定义打印预览方法

首先我们定义一个PrintDocument对象,并实现PrintPage方法: 在一个按钮的单击事件里面实现打印预览:   执行打印预览后我们会看到打印出来的效果:   自定义打印预览 如果是自定义打印预览就需要设置好指定的打印控制器PrintController的属性. PrintController 由 PrintDocument 使用,而这种使用通常不是直接的. .NET Framework 包括从 PrintController 派生的三个打印控制器,可帮助完成常见的任务. 1.Stan

Spark 2.0 预览:更简单,更快,更智能

Apache Spark 2.0 技术预览在 Databricks Community Edition 发布.该预览包使用upstream branch-2.0构建,当启动Cluster时,使用预览包和选择"2.0 (Tech Preview)" 一样简单. 离最终的Apache Spark 2.0发布还有几个星期,现在先来看看有什么新特性: 更简单:SQL和简化的API Spark 2.0依然拥有标准的SQL支持和统一的DataFrame/Dataset API.但我们扩展了Spar

服务器-更新ASP.NET网站时:未预编译文件“XXXX.ASPX”,因此不能请求该文件

问题描述 更新ASP.NET网站时:未预编译文件"XXXX.ASPX",因此不能请求该文件 原网站是把.CS文件预编译成dll,和.aspx文件等预编译成 .compiled文件+一个空的aspx页面(这是个61B的空文件,打开就一句话"这是预编译工具生成的标记文件,不应被删除!"). 好了,介绍好这些后.我源码更新了其中某些页面,包括一些CS文件,用同样的放是编译,挑出了我改动的7个页面的.compiled文件,以及其对应的7个dll.如何对应的呢,是打开.com

浅谈.NET编译时注入(C#--&gt;IL)

原文:浅谈.NET编译时注入(C#-->IL)      .NET是一门多语言平台,这是我们所众所周知的,其实现原理在于因为了MSIL(微软中间语言)的一种代码指令平台.所以.NET语言的编译就分为了两部分,从语言到MSIL的编译(我喜欢称为预编译),和运行时的从MSIL到本地指令,即时编译(JIT).JIT编译分为经济编译器和普通编译器,在这里就不多说了,不是本文的重点.本文主要讨论下预编译过程中我们能做的改变编译情况,改变生成的IL,从编译前后看看微软C#3.0一些语法糖,PostSharp