我有一个方便的实用程序方法,它接受代码并吐出内存中的程序集。 (它使用CSharpCodeProvider
,虽然我不认为这应该重要。)这个程序集与其他任何反射一样工作,但是当与dynamic
关键字一起使用时,它似乎失败了{{1 }}:
'object'不包含'Sound'的定义
示例:
RuntimeBinderException
有谁知道DLR无法解决这个问题的原因?有什么办法可以解决这个问题吗?
编辑:
createAssembly方法:
免责声明:其中一些内容包含扩展方法,自定义类型等。但它应该是不言自明的。
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
答案 0 :(得分:5)
上课public
。
var assembly = createAssembly("public class Dog { public string Sound() ...
^
解决了我机器上的问题。
答案 1 :(得分:0)
这可能是一种解决方法。
//instead of this
//dynamic dog2 = dog;
//try this
dynamic dog2 = DynWrapper(dog);
String test2Result = dog2.Sound();//Now this works.
public class DynWrapper : DynamicObject {
private readonly object _target;
public DynWrapper(object target) {
_target = target;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) {
//for the sake of simplicity I'm not taking arguments into account,
//of course you should in a real app.
var mi = _target.GetType().GetMethod(binder.Name);
if (mi != null) {
result = mi.Invoke(_target, null);
return true;
}
return base.TryInvokeMember(binder, args, out result);
}
}
PS:我尝试将此作为评论发布(因为这是一种解决方法而不是答案)但是不能这样做,因为它很长......