DLR返回类型

7
我需要一些DLR帮助。我正在实现一个IDynamicMetaObjectProvider和DynamicMetaObject,但是我在获取期望的返回类型方面遇到了一些问题。我在元对象中重写了BindInvokeMember方法,我可以看到所有参数类型,但没有返回类型。如果可能的话,有人知道如何获取它吗?我知道返回类型是动态的,但是如果你要调用的东西依赖于返回类型怎么办。除非我知道消费者期望的返回类型,否则我不知道在DynamicMetaObject中执行哪种操作。

更新二

由于它调用了各种工作内容,我无法在此处粘贴我的实际代码。以下是一些示例动态对象代码。
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);
    }
}

这是我正在使用的地方。

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();
}

这是编译器创建的代码。

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();
}
2个回答

5

对于返回结果的标准二进制文件,返回类型几乎总是对象(get、set、操作等)。否则,标准绑定的返回类型为void(例如DeleteMember)。

您还可以从传入绑定程序的ReturnType属性在运行时获取预期的返回类型。


传入的绑定器上没有返回类型。看起来从动态对象调用的方法总是返回动态类型,因此为对象。编译器会生成一些转换代码。 - AbdElRaheim
你的意思是传入的绑定器上没有返回类型?如果你的意思是没有"ReturnType"属性,那么你有旧的代码。你可以清楚地看到这个属性在这里:http://dlr.codeplex.com/SourceControl/changeset/view/27223#581318它是DynamicMetaObject的职责来确保从生成的表达式返回的类型适合标准绑定器。至于转换为动态类型 - 你不需要转换为动态类型。动态对象总是被标记为object类型,并带有额外的元数据,说明它们是动态的。 - Dino Viehland
如果你将“Test”更改为返回TestDynamicObject而不是int,那么你将看到转换请求。因为你在这里返回的是非动态对象,所以C#将只执行其正常的转换语义。在这种情况下,该值已经是一个int,因此不需要进行转换。如果你返回一个double,那么C#将执行其从double到C#的正常转换。 - Dino Viehland
从对象到int的转换通常不是转换语义。反过来是:)那么没有办法知道消费者期望的类型吗?Test方法只是一个测试方法。我实际调用的是将预期返回类型作为参数传递的方法,因此无法进行动态处理。 - AbdElRaheim
当从对象(装箱整数)转换为整数时,它是动态的,这是正常的转换语义。唯一能看到转换的方式是转换后的对象是动态对象。如果您绝对需要看到它,只需创建一个ConvertibleObject,它是实现BindConvert的IDynamicMetaObjectProvider。然后,您可以将返回的任何值包装在ConvertibleObject中,您将取消装箱该值,然后您将看到转换。 - Dino Viehland
显示剩余4条评论

0

看起来我使用的beta版本中至少返回类型是未知的...

我试图使用DLR创建一个p/invoke示例,但似乎除非将预期的返回类型作为参数传递,否则这是不可能的,最终我也这样做了:\ 这对我来说似乎是一种限制... 希望将来能够解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接