Ich habe eine praktische Hilfsmethode, die Code verarbeitet und eine In-Memory-Assembly ausspuckt. (Es verwendet CSharpCodeProvider
, obwohl ich nicht glaube, das sollte egal.) Diese Anordnung funktioniert wie jedes andere mit Reflektion, aber wenn sie mit dem dynamic
Schlüsselwort verwendet, so scheint es, mit einem RuntimeBinderException
zum Scheitern verurteilt:Der Versuch, eine dynamische Methode an einer dynamisch erstellten Assembly zu binden, verursacht eine RuntimeBinderException.
‚Objekt‘ keine Definition für ‚Sound‘ enthält
Beispiel:
var assembly = createAssembly("class Dog { public string Sound() { return \"woof\"; } }");
var type = assembly.GetType("Dog");
Object dog = Activator.CreateInstance(type);
var method = type.GetMethod("Sound");
var test1Result = method.Invoke(dog, null); //This returns "woof", as you'd expect
dynamic dog2 = dog;
String test2Result = dog2.Sound(); //This throws a RuntimeBinderException
Kennt jemand den Grund, warum das DLR nicht in der Lage ist, dies zu umgehen? Gibt es etwas, das getan werden könnte, um dieses Szenario zu beheben?
EDIT:
Create Methode:
Haftungsausschluss: einige dieser Sachen enthält Erweiterungsmethoden, benutzerdefinierte Typen, etc. Es sollte allerdings selbsterklärend sein.
private Assembly createAssembly(String source, IEnumerable<String> assembliesToReference = null)
{
//Create compiler
var codeProvider = new CSharpCodeProvider();
//Set compiler parameters
var compilerParameters = new CompilerParameters
{
GenerateInMemory = true,
GenerateExecutable = false,
CompilerOptions = "/optimize",
};
//Get the name of the current assembly and everything it references
if (assembliesToReference == null)
{
var executingAssembly = Assembly.GetExecutingAssembly();
assembliesToReference = executingAssembly
.AsEnumerable()
.Concat(
executingAssembly
.GetReferencedAssemblies()
.Select(a => Assembly.Load(a))
)
.Select(a => a.Location);
}//End if
compilerParameters.ReferencedAssemblies.AddRange(assembliesToReference.ToArray());
//Compile code
var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParameters, source);
//Throw errors
if (compilerResults.Errors.Count != 0)
{
throw new CompilationException(compilerResults.Errors);
}
return compilerResults.CompiledAssembly;
}
Dummer Fehler meinerseits. 'dynamic' respektiert die Barrierefreiheit, so dass nicht-öffentlicher Code von einer anderen Assembly ausgeführt werden kann, während Reflektion sich nicht um Barrierefreiheit kümmert. Vielen Dank. – MgSam