2012-04-02 10 views
1

私はアプリケーションに特定のモジュラ機能を追加しようとしています。ユーザーが独自のクラスを作成し、実行時にそれらをプログラムにインポートする必要があります。私は新しいクラスの中で関数を呼び出すことができます。実行時にクラスをコンパイルしてアクセスする

例えば、クラスがあり得る:http://pastebin.com/90NTjia9

Iクラスをコンパイルした後のdoSomething()を実行することになります。

どのようにC#でこれを達成できますか?

+1

通常、アプリケーションにフックを提供するdllをユーザーに提供することでこれを行います。これにより、アプリケーションがロードできるDLLを作成することができます。 – mikerobi

+0

私は、単に.csファイルをディレクトリにドロップし、コンパイルして実行できるようにしたプログラムを使用しました。 – JamieB

+1

ここでDarin Dimitrovの答えをご覧ください:http://stackoverflow.com/questions/4718329/compiling-code-dynamically-using-c-sharp –

答えて

4

ユーザーが(彼らはC#クラスを書いている場合、彼らは本当に持つべきなのVisual Studioなど、)必要なツールを持っている場合、彼らはあなたがして、動的にロードすることができ、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); 
} 

あなたがタイプのインスタンスをキャストするabstractclassまたはinterfaceを渡すことができるように、Tジェネリックパラメータがあります:

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ステートメントを提供する必要があります。

実際に完全なクラスを必要としない場合は、how to get an Eval() functionをC#で説明するインターネット上の場所もあります。

関連する問題