如何在c#中安排代码在编译时运行

本文关键字:代码 编译 运行 | 更新日期: 2023-09-27 18:13:10

是否有可能在编译期间执行一些代码?

例如,我想检查一个动态对象的请求方法是否存在于泛型类的参数类型中。

 // This code has no actual purpose, just as an example
 public class Sample<T>
 {
     public Sample<T>(T instance)
     {
         foo = Value = instance;
         /* adding some extra code(e.g. logging) to the methods of T, by
inserting a "M" in front of the method names of T */
     }
     public T Value { get; }
     public dynamic foo { get; }
 }

如何使用

var foo = new Sample<string>("hey");
foo.MSubstring(0,0);

现在我想知道是否有可能在编译时执行代码,例如,在运行前抛出异常,表明foo.MgetSize()不存在于t中

(这个问题只是关于如何在编译时执行代码,这个示例不是一个真正的问题。)

我没有一个计划如何做那件事。也许用#if之类的东西?

如何在c#中安排代码在编译时运行

是的,在构建时执行代码是可能的。毕竟,构建程序的工具本身就是代码。

你问的是如何自定义构建过程并在此过程中执行一些额外的逻辑。如何做到这一点取决于您正在使用的实际工具-例如,对于Visual Studio和MSBuild系统,您可以参考MSDN文档中的自定义构建步骤和构建事件。

您的自定义构建工具将是什么样子取决于它将在过程的哪个部分启动。如果它与源代码一起工作,它需要能够解析c#源代码(也可能是Visual Studio项目文件)。如果它通过验证发出的程序集(在典型构建过程结束时生成的二进制文件)来工作,那么它可以简单地使用反射来检测您想要的错误。我觉得后者更方便。

理论上,您可以使用T4进行编译时检查。

另一种方法是使用支持编译时宏的语言。例如,Nemerle或Boo。

也许你可以用Roslyn。

在c#中,您可以运行一些刚刚在"Post build"中编译的代码。

你可以使用像Post#这样的工具,通过创建属性来做你想做的检查。参见:https://www.postsharp.net/product/how-it-works

在其他语言中,如Jai,可以很容易地做到这一点。参见"任意编译时代码执行"

某个函数可能存在也可能不存在的场景有点粗略。最好在接口中包含Convert方法,对象本身可以告诉您它是否实现了该功能,并返回一个具有适当接口的对象,如果没有返回则返回null。

虽然它可以用预处理器完成,但我不推荐它。您所描述的场景意味着您将包含一个为对象定义该方法的头,不定义该方法的头。你得不到真正的动力。在header中,使用

#define HASMETHOD

,在你的执行器中使用:

#ifdef HASMETHOD
   foo.MSubstring(0, 0);
#endif

但是,我强烈建议不要这样做。使用在运行时调用的方法来确定,该方法返回要调用的接口。

根据定义,不能在编译时执行代码。但是,您可以在加载时(实际上在创建第一个实例或引用任何静态成员之前)使用静态构造函数执行代码:

链接到msdn