Following up on this excellent answer, I'm wondering if the DLR using the dynamic
keyword can allow a less verbose way of writing code for the generated assembly.
For example, can the aforementioned answer's code:
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[] { });
}
become something like:
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();
}
Yes, you can do that and it works well. However, while using the dynamic keyword is more convenient, it utilizes late-binding and is still just as unsafe, in that sense, as explicitly using reflection. If your design allows it, it is even better to use a shared interface or base class for early-binding. You can do this by creating a public type in your assembly or in a third, shared assembly, and then add a reference to that assembly from the new one you are dynamically compiling. Then, in the generated code, you can inherit from that shared type in the referenced assembly. For instance, create an interface:
Then dynamically compile the assembly like this:
Depending on how much control you have over the dynamic code, this may or may not be possible, but when it is, it's nice to have the compile-time type-checking. For instance, if you tried to execute:
That second line would immediately fail to compile because it's spelled wrong, whereas with the dynamic keyword or reflection, that line would successfully compile but it would cause a run-time exception. For instance, the following will not get a compile-time error:
That is one of the scenarios that the DLR was designed for. You can use it that way to invoke members of a dynamically loaded type while avoiding all of the extra typing from manually calling
.GetMethod()
and.Invoke()
.