【问题标题】:DLR return typeDLR 返回类型
【发布时间】:2009-09-01 00:55:59
【问题描述】:

我需要一些 DLR 帮助。我正在实现 IDynamicMetaObjectProvider 和 DynamicMetaObject 但在获取预期的返回类型时遇到了一些问题。我在元对象中覆盖了 BindInvokeMember,我可以看到所有 args 类型但没有返回类型。如果可能的话,有人知道我是怎么做到的吗?我知道返回类型是动态的,但如果你调用的东西依赖于返回类型怎么办。除非我知道消费者期望的返回类型,否则我不知道在 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();
}

【问题讨论】:

    标签: c# dynamic-language-runtime dynamic-binding


    【解决方案1】:

    对于返回某些内容的标准二进制文件,返回类型几乎总是对象(get、set、操作等)。否则,标准绑定(例如 DeleteMember)无效。

    您还可以在运行时从传入活页夹上的 ReturnType 属性获取预期的返回类型。

    【讨论】:

    • 传入的活页夹没有返回类型。看起来像调用动态对象的方法总是返回一个动态类型,因此是对象。编译器会生成一些转换代码。
    • 传入的活页夹没有返回类型是什么意思?如果您的意思是没有“ReturnType”属性,那么您有旧的来源。您可以在这里清楚地看到这个属性:dlr.codeplex.com/SourceControl/changeset/view/27223#581318 DynamicMetaObject 负责确保从生成的表达式返回的类型与标准绑定器匹配。至于转换为动态 - 您不需要转换为动态。动态对象总是被输入到带有额外元数据的对象中,说明它们是动态的。
    • 是的,我可以在 codeplex 上看到该属性。它在我使用的 beta 1 位中不存在。我想我将不得不等待下一次vs2010刷新。我所说的转换的意思是下面的代码使用它也会生成一个转换。我记得在某处读到动态对象方法返回对象并且必须进行转换。这不正确吗?编译器生成的代码在我上面的帖子中。这在最新版本中是否也发生了变化?对象 x = new DynamicTest(); int w = x.Test();
    • 应该不需要任何转换。动态对象只是一个带有属性的对象,表示它是动态的。在发布的代码中,您似乎在 C# 代码中对 int 进行了强制转换。如果 InvokeMember 的结果不是 IDO,那么您自己将永远不会看到 Convert 调用 - 相反,C# binder 将处理普通 .NET 类型的转换。如果这仍然不能回答您可能想要发布您的 C# 代码和 DynamicMetaObject 实现的问题。
    • 我自己不做演员。我更新了帖子以包含代码。同样是这个 vs2010 beta 1,所以行为可能在最新版本中发生了变化。
    【解决方案2】:

    看来返回类型至少是我使用的 beta 不知道...

    我试图使用 DLR 制作一个 p/invoke 示例,但似乎这是不可能的,除非您将预期的返回类型作为我最终做的参数传递:\ 这在我看来是一个限制.. . 希望它会在未来得到解决。

    【讨论】:

      猜你喜欢
      • 2021-03-11
      • 2014-12-09
      • 2021-04-15
      • 2020-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      相关资源
      最近更新 更多