简体   繁体   English

在C#中使用反射调用动态方法

[英]Call dynamic methods using reflection in C#

I have a DynamicObject-based class that implements an interface dynamically (via TryGet* and TryInvoke*). 我有一个基于DynamicObject的类,该类可以动态地(通过TryGet *和TryInvoke *)实现接口。 I want to call the methods that it implements using reflection. 我想调用它使用反射实现的方法。 The problem is that it throws a TargetException (Object does not match target type). 问题在于它抛出TargetException(对象与目标类型不匹配)。

Like I said, it's dynamic, so it forwards the calls via a series of connections as text to another program, which then calls the destination method using reflection. 就像我说的那样,它是动态的,因此它通过一系列连接将调用作为文本转发到另一个程序,然后使用反射调用目标方法。 It is basically a proxy class. 它基本上是一个代理类。 The method names are known at compile time (because of the interface), but are called externally. 方法名称在编译时(由于接口)是已知的,但是在外部被调用。

typeof(ITelescope).GetMethod(Console.ReadLine()).Invoke(prox,null);

ITelescope is the interface, prox is the dynamic object. ITelescope是接口, prox是动态对象。

Unfortunately, dynamically defined methods are not available via reflection. 不幸的是,动态定义的方法无法通过反射获得。 Part of this is due to the fact that they are truly dynamic - you could have a dynamic object where ANY method was valid, so there is no way for reflection to work properly in that scenario. 部分原因是由于它们真正是动态的-您可能在任何方法都有效的情况下拥有一个动态对象,因此在这种情况下反射无法正常工作。 (ie: what would GetMethods() return?) (即: GetMethods()返回什么?)

If the object is a dynamic object, the best option is usually to just assign it to a dynamic , and use the dynamic binding to get your method call: 如果对象是动态对象,最好的选择通常是将其分配给dynamic ,然后使用动态绑定来获取方法调用:

dynamic yourObj = prox;
yourObj.Unpark();

If your trying to do something a little more meta than just using the dynamic keyword, you might be interested in a framework I wrote ImpromptuInterface (apache licensed, can be found in nuget ). 如果您尝试做一些比仅使用dynamic关键字更多的元操作,那么您可能会对我编写的ImpromptuInterface(Apache许可,可以在nuget中找到)框架感兴趣。

Since it looks like you have an interface that matches up with your dynamic object, you can use Impromptu to wrap your dynamic object with an interface impromptu will dynamically emit an object that statically has an interface and will forward calls from that interface to a dynamic object using the dlr. 因为看起来您有一个与动态对象匹配的接口,所以可以使用Impromptu 用接口包装动态对象,即兴将动态发出一个静态具有接口的对象,并将调用从该接口转发到动态对象使用dlr。

ITelescope iprox = Impromptu.ActLike(prox);
prox.Unpark();

Or if you just want to call a method of a dynamic object by a string name, similar to reflection, it also has a bunch of reflection like methods , that dynamically invoke dlr calls. 或者,如果您只想通过字符串名称来调用动态对象的方法(类似于反射),则它还具有一堆类似于方法反射 ,它们可以动态调用dlr调用。 It is less efficient than the interface way, but more efficient than reflection. 它比接口方式效率低,但比反射方式效率高。

Impromptu.InvokeMember(prox,"Unpark");

Although you can not invoke a dynamic method with reflection, you can invoke TryGet.../TryInvoke... methods of DynamicObject which in turn execute your dynamic method... 尽管无法通过反射调用动态方法,但是可以调用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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM