-->

DLR return type

2019-04-07 10:11发布

问题:

I need some DLR help. I am implementing an IDynamicMetaObjectProvider and DynamicMetaObject but I am having some issues getting the expected return type. I am overiding BindInvokeMember in the metaobject, I can see all the args types but no return type. Anyone know how I get to it if possible? I know the return type is dynamic but what if the thing you are invoking is dependent on a return type. I don't know which action to perform in the DynamicMetaObject unless I know the return type the consumer is expecting.

Update Two

I cant paste my actual code here since it calls all kinds of work stuff. Some sample dynamic object code is below.

public class TestDynamicMetaObject : DynamicMetaObject
{
    public TestDynamicMetaObject(Expression expression, object value)
        : base (expression, BindingRestrictions.Empty, value)
    {
    }

    public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
    {
        Delegate method = new Func<int>(Test);
        return new DynamicMetaObject(
            Expression.Call(method.Method),
            BindingRestrictions.GetInstanceRestriction(Expression,Value),
            Value
        );
    }

    public static int Test()
    {
        return 10;
    }

}
public class TestDynamicObject : IDynamicMetaObjectProvider
{
    DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
    {
        return new TestDynamicMetaObject(parameter, this);
    }
}

Here is where I am using.

static void Main(string[] args)
{
    try
    {
        dynamic x = new TestDynamicObject();
        int gg= x.Test();
        Console.WriteLine(gg);
    }
    catch (Exception excep)
    {
        Console.WriteLine(excep);
    }
    Console.ReadLine();
}

Here is the code that the compiler creates.

private static void Main(string[] args)
{
    try
    {
        object x = new TestDynamicObject();
        if (<Main>o__SiteContainer0.<>p__Site1 == null)
        {
            <Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, int>>.Create(new CSharpConvertBinder(typeof(int), CSharpConversionKind.ImplicitConversion, false));
        }
        if (<Main>o__SiteContainer0.<>p__Site2 == null)
        {
            <Main>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, object, object>>.Create(new CSharpInvokeMemberBinder(CSharpCallFlags.None, "Test", typeof(Program), null, new CSharpArgumentInfo[] { new CSharpArgumentInfo(CSharpArgumentInfoFlags.None, null) }));
        }
        Console.WriteLine(<Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, <Main>o__SiteContainer0.<>p__Site2.Target(<Main>o__SiteContainer0.<>p__Site2, x)));
    }
    catch (Exception excep)
    {
        Console.WriteLine(excep);
    }
    Console.ReadLine();
}

回答1:

For the standard binaries which return something the return type is almost always object (get, set, operations, etc...). Otherwise it's void for the standard bindings (e.g. DeleteMember).

You can also get the expected return type at runtime from the ReturnType property on the incoming binder.



回答2:

It appears the return type at least is the beta i was using is not know...

I was trying to make a p/invoke example using the DLR but it seems like this is not possible unless you pass in the expected return type as a parameter which I ended up doing :\ This seems to me like a limitation... Hopefully it will be addressed in the future.