如何在编译时注入C#代码?

时间:2009-08-29 22:05:44

标签: c# .net reflection aop tracing

我希望能够使用自定义Trace属性修饰任何方法,并且应该在编译时将一些代码注入到该方法中。

例如:

[Trace]
public void TracedMethod(string param1)
{
   //method body
}

应该成为:

public void TracedMethod(string param1)
{
   Log.Trace("TracedMethod", "param1", param1);
   //method body
}

在这种情况下,注入的代码取决于方法名称和方法参数,因此应该可以推断出这些信息。

有谁知道如何做到这一点?

2 个答案:

答案 0 :(得分:13)

要在C#中进行面向方面编程,您可以使用PostSharp

The homepage甚至会显示Trace示例,就像您要求的那样!)

答案 1 :(得分:2)

这可以通过程序转换系统轻松完成。

DMS Software Reengineering Toolkit是一个通用程序转换系统,可以与多种语言(C ++,COBOL,Java,EcmaScript,Fortran,...)一起使用,也可以与C#一起使用。

DMS解析源代码,构建抽象语法树,并允许您应用源到源模式,将您的代码从一个C#程序转换为另一个具有您希望的属性的程序。完全完成您指定的任务的转换规则是:

domain CSharp.

insert_trace():method->method
  "[Trace]
   \visibility \returntype \methodname(string \parametername)
   { \body  } "
      ->
  "\visibility \returntype \methodname(string \parametername)
   { Log.Trace(\CSharpString\(\methodname\),
               \CSharpString\(\parametername\),
               \parametername);
      \body } "

引号(“)不是CSharp引号;相反,它们是”域引号“,并表示引号内的内容是CSharp语法(因为我们说”域CSharp“)。\ foo符号是元语法。

此规则匹配代表您使用 [Trace]注释指定的方法的AST,并将该AST重写为跟踪形式。然后将生成的AST重新打印回源表单,您可以编译。您可能需要其他规则来处理其他参数组合;实际上,您可能会将参数处理概括为为每个标量参数生成(在可行的情况下)字符串值。

应该很清楚,你可以做更多的事情,而不仅仅是记录这个,而不仅仅是面向方面的编程,因为你可以表达任意变换,而不仅仅是前后行动。