У меня есть удобный полезный метод, который принимает код и выплескивает сборку в памяти. (Он использует CSharpCodeProvider
, хотя я не думаю, что должно иметь значения.) Эта сборка работает как любой другой с отражением, но при использовании с dynamic
ключевого слова, это, кажется, не в состоянии с RuntimeBinderException
:Попытка связать динамический метод с динамически созданной сборкой вызывает RuntimeBinderException
«объект» не содержит определение для «звука»
Пример:
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
кто-нибудь знает причину, почему DLR не умеет справиться с этим? Есть ли что-то, что можно было бы сделать, чтобы исправить этот сценарий?
EDIT:
метод createAssembly:
Отказ от ответственности: некоторые из этих вещей содержит методы расширения, пользовательские типы, и т.д. Это должно быть само за себя, хотя.
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;
}
Глупые ошибки с моей стороны. 'dynamic' уважает доступность, поэтому он не может выполнять непубличный код с другой сборки, в то время как отражение не имеет отношения к доступности. Благодарю. – MgSam