5

この優れた回答をフォローアップすると、dynamicキーワードを使用する DLR によって、生成されたアセンブリのコードをより簡潔に記述できるようになるかどうか疑問に思っています。

たとえば、前述の回答のコードは次のようになります。

using (Microsoft.CSharp.CSharpCodeProvider foo = 
           new Microsoft.CSharp.CSharpCodeProvider())
{
    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() {  
            GenerateInMemory = true 
        }, 
        "public class FooClass { public string Execute() { return \"output!\";}}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");
    var obj = Activator.CreateInstance(type);
    var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}

次のようになります。

using (Microsoft.CSharp.CSharpCodeProvider foo = 
           new Microsoft.CSharp.CSharpCodeProvider())
{
    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() {  
            GenerateInMemory = true 
        }, 
        "public class FooClass { public string Execute() { return \"output!\";}}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");
    dynamic obj = Activator.CreateDynamicInstance(type);
    var output = obj.Execute();
}
4

2 に答える 2

7

はい、それを行うことができ、うまく機能します。ただし、 dynamic キーワードを使用する方が便利ですが、遅延バインディングを利用するため、その意味では、リフレクションを明示的に使用するのと同じくらい安全ではありません。設計で許可されている場合は、事前バインディングに共有インターフェイスまたは基本クラスを使用することをお勧めします。これを行うには、アセンブリまたは 3 番目の共有アセンブリにパブリック型を作成し、動的にコンパイルする新しいアセンブリからそのアセンブリへの参照を追加します。次に、生成されたコードで、参照されているアセンブリの共有型から継承できます。たとえば、インターフェイスを作成します。

public interface IFoo
{
    string Execute();
}

次に、次のようにアセンブリを動的にコンパイルします。

using (Microsoft.CSharp.CSharpCodeProvider foo = new Microsoft.CSharp.CSharpCodeProvider())
{
    var params = new System.CodeDom.Compiler.CompilerParameters();
    params.GenerateInMemory = true;

    // Add the reference to the current assembly which defines IFoo
    params.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

    // Implement the IFoo interface in the dynamic code
    var res = foo.CompileAssemblyFromSource(params, "public class FooClass : IFoo { public string Execute() { return \"output!\";}}");
    var type = res.CompiledAssembly.GetType("FooClass");

    // Cast the created object to IFoo
    IFoo obj = (IFoo)Activator.CreateInstance(type);

    // Use the object through the IFoo interface
    obj.Execute();
}

動的コードをどの程度制御できるかによって、これが可能である場合と不可能である場合がありますが、可能である場合は、コンパイル時の型チェックがあると便利です。たとえば、実行しようとした場合:

IFoo obj = (IFoo)Activator.CreateInstance(type);
obj.Execcute();

その 2 行目はスペルが間違っているため、すぐにコンパイルに失敗しますが、dynamic キーワードまたはリフレクションを使用すると、その行は正常にコンパイルされますが、実行時例外が発生します。たとえば、次の場合、コンパイル時エラーは発生しません。

dynamic obj = Activator.CreateDynamicInstance(type);
obj.Execcute();
于 2012-06-06T13:26:24.173 に答える