3

I have a DynamicObject-based class that implements an interface dynamically (via TryGet* and 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).

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.

4

3 回答 3

4

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?)

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 yourObj = prox;
yourObj.Unpark();
于 2012-10-22T17:07:43.960 回答
3

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).

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.

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. It is less efficient than the interface way, but more efficient than reflection.

Impromptu.InvokeMember(prox,"Unpark");
于 2012-10-22T17:35:41.980 回答
3

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...

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();
    }
}
于 2012-10-22T18:39:58.430 回答