在运行时动态创建函数

它可能甚至不可能这样做,但无论如何我会问。 是否有可能创建一个接收字符串的函数,然后将其用作lambda中使用的转到运算符(=>)的右侧参数?

实际上,我想要做的是能够在运行时重新定义特定类的特定方法。 我想在程序运行时写下一个函数并将其附加到委托。 可能吗?

最简单的方法可能就是TcKs建议的DLINQ。

最快(我相信,在3.5中)是创建DynamicMethod 。 它也是最可怕的方法。 你实际上是使用IL构建一个方法,它与在机器语言中编写代码的感觉大致相同。

我需要这样做以动态地将事件处理程序附加到某些事物中(好吧,我不需要这样做,我只是想让unit testing事件更容易)。 当时看起来有点令人生畏,因为我不知道有关IL的废话,但我想出了一个简单的方法来实现这一目标。

你所做的是创建一个完全符合你想要的方法。 越紧凑越好。 如果我能弄清楚你想要做什么,我会提供一个例子。 您在DLL项目中的类中编写此方法,并在发布模式下编译它。 然后在Reflector中打开DLL并反汇编您的方法。 Reflector为您提供了您希望反汇编的语言选项 – 选择IL。 现在,您需要添加到动态方法中的确切调用。 只需按照MSDN上的示例,为您反映的方法代码切换示例的IL。

动态方法一旦构造,就会以与编译方法大致相同的速度调用(看到一个测试,其中动态方法可以在约20ms内被调用,其中reflection超过200ms)。

你有几种方法可以做到这一点:

  • 动态创建lambda表达式(查看动态LINQ:第1部分 )
  • 动态创建CodeDom模型并在运行时编译它(查看CodeDom.Compiler命名空间
  • 动态创建C#/ VB.NET源代码并在运行时编译它(查看CSharpCodeProvider和VBCodeProvider类)
  • 动态创建对象模型,可以执行与方法相同的操作(查看策略设计模式

您的问题很不清楚,但您当然可以使用表达式树在执行时动态创建委托。 (还有其他方法可以做到这一点,比如CodeDOM,但是表达树如果能够完成所有你需要的就更方便了。但是,你可以做的事情有很大的限制。)

但是,使用带有一些捕获变量的lambda表达式通常更容易。

例如,要创建一个将指定数量添加到任何整数的函数,您可以编写:

static Func CreateAdder(int amountToAdd) { return x => x + amountToAdd; } ... var adder = CreateAdder(10); Console.WriteLine(adder(5)); // Prints 15 

如果这没有帮助,请澄清您的问题。

并不是说我推荐其他更好的选项,但是有 7种方法,那就是在System.Reflection.Emit命名空间中使用AssemblyBuilderMethodBuilderTypeBuilderMethodBuilder来创建动态程序集。 这与使用DynamicMethod伏都DynamicMethod相同。

例如,您可以在运行时使用这些来为类型创建代理类并覆盖该类型上的虚拟方法。

为了让你开始这里是一些代码……

 using System; using System.Reflection; using System.Reflection.Emit; var myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName("Test"), AssemblyBuilderAccess.RunAndSave); var myModule = myAssembly.DefineDynamicModule("Test.dll"); var myType = myModule.DefineType("ProxyType", TypeAttributes.Public | TypeAttributes.Class, typeof(TypeToSeverelyModifyInAnUglyWayButItsNecessary)); var myMethod = myType.DefineMethod("MethodNameToOverride", MethodAttributes.HideBySig | MethodAttributes.Public, typeof(void),Type.EmptyTypes); var myIlGenerator = myMethod.GetILGenerator(); myIlGenerator.Emit(OpCodes.Ret); var type = myType.CreateType(); 

您应该首先检查您的问题是否可以通过简单的多态解决。 除非您将抽象互操作性定义为另一种语言或编辑编译器,否则尝试在运行时更改方法可能是解决问题的错误方法。

如果将方法声明为虚拟,则可以使用Castle的DynamicProxy在运行时替换动态生成的(使用其他答案的方法之一)实现:

Castle DynamicProxy是一个用于在运行时动态生成轻量级.NET代理的库。 代理对象允许在不修改类的代码的情况下拦截对对象成员的调用。 类和接口都可以代理,但只能拦截虚拟成员。

你问题中的第二段表明你真正想要的是直截了当的IOC (控制反转)

您不是声明类的实例,而是声明接口的实例,并根据您选择的条件,使用特定的重写类及其中的正确方法。 希望有道理。