简体   繁体   English

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

[英]How to inject C# code at compile-time?

I would like to be able to decorate any method with a custom Trace attribute and some piece of code should be injected into that method at compilation. 我希望能够使用自定义Trace属性修饰任何方法,并且应该在编译时将一些代码注入到该方法中。

For example: 例如:

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

should become: 应成为:

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

In this case, the injected code depends on the method name and method parameters, so it should be possible to infer this information. 在这种情况下,注入的代码取决于方法名称和方法参数,因此应该可以推断出此信息。

Does anyone know how to accomplish this? 有谁知道如何做到这一点?

To do Aspect Oriented Programming in C#, you can use PostSharp . 要在C#中进行面向方面编程,可以使用PostSharp

( The homepage even shows a Trace example, just like you're asking for!) 主页甚至显示了Trace示例,就像您要求的那样!)

This can be easily done with a program transformation system. 这可以通过程序转换系统轻松完成。

The DMS Software Reengineering Toolkit is a general purpose program transformation system, and can be used with many languages (C++, COBOL, Java, EcmaScript, Fortran, ..) as well as specifically with C#. DMS软件再造工具包是一个通用程序转换系统,可以与多种语言(C ++,COBOL,Java,EcmaScript,Fortran,...)一起使用,也可以与C#一起使用。

DMS parses source code, builds Abstract Syntax Trees, and allows you to apply source-to-source patterns to transform your code from one C# program into another with whatever properties you wish. DMS解析源代码,构建抽象语法树,并允许您应用源到源模式,将您的代码从一个C#程序转换为另一个具有您希望的属性的程序。 THe transformation rule to accomplish exactly the task you specified would be: 完全完成您指定的任务的转换规则是:

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 } "

The quote marks (") are not CSharp quote marks; rather, they are "domain quotes", and indicate that the content inside the quote marks is CSharp syntax (because we said, "domain CSharp"). The \\foo notations are meta syntax. 引号(“)不是CSharp引号;相反,它们是”域引号“,并表示引号内的内容是CSharp语法(因为我们说”域CSharp“)。\\ foo符号是元句法。

This rule matches the AST representing the method you specified with the [Trace] annotation, and rewrites that AST into the traced form. 此规则与表示您使用 [Trace]注释指定的方法的AST匹配,并将该AST重写为跟踪形式。 The resulting AST is then prettyprinted back into source form, which you can compile. 然后将生成的AST重新打印回源表单,您可以编译。 You probably need other rules to handle other combinations of arguments; 您可能需要其他规则来处理其他参数组合; in fact, you'd probably generalize the argument processing to produce (where practical) a string value for each scalar argument. 实际上,您可能会将参数处理概括为为每个标量参数生成(在可行的情况下)字符串值。

It should be clear you can do a lot more than just logging with this, and a lot more than just aspect-oriented programming, since you can express arbitrary transformations and not just before-after actions. 应该清楚的是,你可以做更多的事情,而不仅仅是记录这个,而不仅仅是面向方面的编程,因为你可以表达任意转换,而不仅仅是前后行动。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM