从字符串加载方法体?

时间:2013-12-06 01:20:00

标签: c# reflection configuration

对于非常特殊情况,我希望能够在配置条目中存储C#代码,并在运行时使用此代码填充空函数。例如,假设在初始运行时我开始使用如下方法:

bool Evaluate(int number)
{
   return false;
}

我有一个如下所示的配置条目:

<add key="EvaluateCode" value="if (number > 5) { return true; } else { return false; }"/>

加载 EvaluateCode 配置条目后,我想替换 Evaluate 的函数体,使它看起来像这样:

bool Evaluate(int number)
{
   if (number > 5) { return true; } else { return false; }
}

完成“替换”之后, Evaluate 函数应该按照代码的规定运行,就像代码没有动态加载一样。

我怎样才能在C#中实现这个目标?

加分:实施此功能会有什么风险?我该如何减轻这些风险?

2 个答案:

答案 0 :(得分:2)

基本上你要求能够在运行时编译c#代码,这是可能的,并且描述为here

答案 1 :(得分:1)

这听起来很有趣..所以我决定尝试一下。

无需upvote ..只需在此处弹出,以便将来可以参考:)

鉴于以下类别:

class DynamicMethodTest {
    private MethodInfo _methodToCall;
    private object _obj;

    public void PerformInjection(string newBody) {
        using (var codeProvider =
       new Microsoft.CSharp.CSharpCodeProvider()) {
            var res = codeProvider.CompileAssemblyFromSource(
                new System.CodeDom.Compiler.CompilerParameters() {
                    GenerateInMemory = true
                },
                "public class StubClass { public bool Evaluate(int number) { " + newBody + " }}"
            );

            var type = res.CompiledAssembly.GetType("StubClass");

            _obj = Activator.CreateInstance(type);

            _methodToCall = _obj.GetType().GetMethod("Evaluate");
        }
    }

    public bool Evaluate(int number) {
        if (_methodToCall != null)
            return (bool)_methodToCall.Invoke(_obj, new object[] { number });

        return false;
    }
}

我们可以这样做:

public class Program {
    public static void Main() {
        var dynamicTest = new DynamicMethodTest();

        Console.WriteLine(dynamicTest.Evaluate(15)); // False

        dynamicTest.PerformInjection("if (number > 5) { return true; } else { return false; }");

        Console.WriteLine(dynamicTest.Evaluate(15)); // True

        Console.Read();
    }

}

这导致:

False
True

作为输出。基本上,在“注入”之前(它不是真正的注入......它更像是一个fascade),该方法返回false。在“注入”之后,它返回true(如预期的那样)。