2012-04-02 128 views
1

我想一些具体的模块化functonality添加到我的应用程序访问类,我需要用户能够创建他们自己的类,然后让他们在运行时导入到程序中,这些类会按照特定的所以我可以在他们的新类中调用函数。编译和运行时

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

我将编译类,然后执行doSomething的();

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

+1

通常,您将通过为用户提供的是提供给您的应用程序挂钩一个dll做到这一点。这使他们能够创建一个你的应用程序可以加载的dll。 – mikerobi 2012-04-02 16:56:03

+0

我使用,让您只需拖放.cs文件到一个目录,并将它编译和运行程序。 – JamieB 2012-04-02 16:58:24

+1

看到Darin Dimitrov的答案在这里:http://stackoverflow.com/questions/4718329/compiling-code-dynamically-using-c-sharp – 2012-04-02 17:02:41

回答

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泛型参数是有让您可以通过一个abstractclassinterface的类型实例转换为:

public interface IDoSomething 
{ 
    bool DoSomething(); 
} 

您的用户INH从这个接口ERIT当他们写自己的类:

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

这可以让你保持类型安全和直接调用类的方法,而不是依赖于反思这样做。

如果你真的想你的用户提供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的地方,如果你并不真的需要一个成熟的类。