我有一个基于DynamicObject的类,它动态地实现了一个接口(通过TryGet *和TryInvoke *)。我想调用它使用反射实现的方法。问题是它抛出了一个TargetException(Object与目标类型不匹配)。
就像我说的那样,它是动态的,所以它通过一系列连接将调用作为文本转发给另一个程序,然后使用反射调用目标方法。它基本上是一个代理类。方法名称在编译时是已知的(因为接口),但在外部调用。
typeof(ITelescope).GetMethod(Console.ReadLine()).Invoke(prox,null);
ITelescope是界面,prox
是动态对象。
答案 0 :(得分:4)
不幸的是,动态定义的方法不能通过反射获得。部分原因在于它们是真正的动态 - 你可以拥有一个动态对象,其中任何方法都是有效的,因此在这种情况下反射无法正常工作。 (即:GetMethods()
会返回什么?)
如果对象是动态对象,最好的选择通常是将其分配给dynamic
,并使用动态绑定来调用方法:
dynamic yourObj = prox;
yourObj.Unpark();
答案 1 :(得分:3)
如果你试图做一些比使用动态关键字更多元的东西,你可能会对我写的ImpromptuInterface(apache许可,可以在nuget中找到)的框架感兴趣。
由于看起来你有一个与你的动态对象匹配的接口,你可以使用Impromptu来wrap your dynamic object with an interface即兴将动态发出一个静态有接口的对象,并将来自该接口的调用转发给动态使用dlr的对象。
ITelescope iprox = Impromptu.ActLike(prox);
prox.Unpark();
或者,如果您只想通过字符串名称调用动态对象的方法,类似于反射,它还有一堆reflection like methods,可以动态调用dlr调用。它的效率低于接口方式,但比反射效率更高。
Impromptu.InvokeMember(prox,"Unpark");
答案 2 :(得分:3)
虽然您无法使用反射调用动态方法,但您可以调用DynamicObject的 TryGet ... / TryInvoke ... 方法,然后执行您的动态方法......
dynamic obj = new MyDyn();
Console.WriteLine(obj.Text);
string methodName = "YourDynamicMethod";
var p1 = new ParameterModifier(2);
p1[0] = false; p1[1] = true;
var args = new object[] { new MemberBinder(methodName, true), null };
var res = typeof(DynamicObject).InvokeMember(
"TryGetMember",
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
obj,
args,
new ParameterModifier[] { p1 },
null,
null);
var result = args[1];
public class MyDyn : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = "#" + binder.Name + "#";
return true;
}
}
public class MemberBinder : GetMemberBinder
{
public MemberBinder(string name, bool ignoreCase) : base(name, ignoreCase)
{
}
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
throw new NotImplementedException();
}
}