2012-04-02 127 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的地方,如果你並不真的需要一個成熟的類。