在运行时编译和访问类

时间:2012-04-02 16:52:50

标签: c# winforms console runtime

我正在尝试为我的应用程序添加一些特定的模块化功能,我需要用户能够创建自己的类,然后在运行时将它们导入到程序中,这些类将遵循特定的模板,因此我可以调用函数在他们的新课程中。

例如,一个类可以是:http://pastebin.com/90NTjia9

我会编译该类,然后执行doSomething();

我如何在C#中实现这一目标?

1 个答案:

答案 0 :(得分:4)

如果您的用户拥有必要的工具(例如Visual Studio,如果他们正在编写C#类,他们应该),他们可以为您提供DLL,然后您可以加载动态:

private static T CreateInstance(string assemblyName, string typeName)
{
    var assembly = Assembly.LoadFrom(assemblyName);

    if (assembly == null)
        throw new InvalidOperationException(
           "The specified assembly '" + assemblyName + "' did not load.");

    Type type = assembly.GetType(typeName);
    if (type == null)
        throw new InvalidOperationException(
           "The specified type '" + typeName + "' was not found in assembly '" + assemblyName + "'");

    return (T)Activator.CreateInstance(type);
}

存在T通用参数,以便您可以传递abstract classinterface以将类型实例强制转换为:

public interface IDoSomething
{
    bool DoSomething();
}

您的用户在编写自己的类时会从此界面继承:

public class UserDefinedClass : IDoSomething
{
    public bool DoSomething()
    {
        // Implementation here.
    }
}

这允许您保留类型安全性并直接调用类方法,而不是依赖于Reflection来执行此操作。

如果您真的希望用户提供C#源代码,您可以compile their class at runtime这样:

private Assembly BuildAssembly(string code)
{
    var provider = new CSharpCodeProvider();
    var compiler = provider.CreateCompiler();
    var compilerparams = new CompilerParameters();
    compilerparams.GenerateExecutable = false;
    compilerparams.GenerateInMemory = true;
    var results = compiler.CompileAssemblyFromSource(compilerparams, code);
    if (results.Errors.HasErrors)
    {
        var errors = new StringBuilder("Compiler Errors :\r\n");
        foreach (CompilerError error in results.Errors )
        {
            errors.AppendFormat("Line {0},{1}\t: {2}\n", 
                   error.Line, error.Column, error.ErrorText);
        }
        throw new Exception(errors.ToString());
    }
    else
    {
        return results.CompiledAssembly;
    }
}

然后,您只需在上面的CreateInstance代码中替换生成的程序集,而不是外部加载的程序集。请注意,您的用户仍需要在其班级顶部提供相应的using语句。

互联网上还有一些地方在C#中解释how to get an Eval() function,以防你真的不需要一个完整的课程。