【问题标题】:Is there a C# equivalent to Ruby's `respond_to?`?是否有与 Ruby 的 `respond_to?` 等效的 C#?
【发布时间】:2009-12-09 23:06:52
【问题描述】:

我正在编写一个简单的包装器来“躲避”dynamic 对象对已知接口:

interface IFoo { string Bar(int fred); }

class DuckFoo : IFoo
{
    private readonly dynamic duck;

    public DuckFoo(dynamic duck)
    {
        this.duck = duck;
    }

    public string Bar(int fred)
    {
        return duck.Bar(fred);
    }
}

如果dynamic 对象可以响应Bar 签名,这将正常工作。但如果它不能,只有当我调用Bar 时才会失败。我希望它可以更快地失败,即在构造 DuckFoo 包装器时进行参数验证。像这样的:

public DuckFoo(dynamic duck)
{
    if(/* duck has no matching Bar method */)
        throw new ArgumentException("duck", "Bad dynamic object");
    this.duck = duck;
}

在 Ruby 中,有一个 respond_to? 方法可用于测试对象是否“具有”某种方法。有没有办法在 C# 4 中使用动态对象进行测试?

(我知道即使进行此检查,Bar 调用稍后也可能会失败,因为 duck 的动态特性使其稍后停止响应方法。)

【问题讨论】:

    标签: c# dynamic


    【解决方案1】:

    您可以在构造时检查使用反射包装的对象上可用的方法。

    只需在接口和传入的类型上调用Type.GetMethods(),并确保存在相应的方法。


    编辑:

    正如itowlson 所建议的,还有一个处理动态类型的选项。如果您检查传递的对象上是否存在 IDynamicMetaObjectProvider 接口,则可以调用 IDynamicMetaObjectProvider.GetMetaObject().GetDynamicMemberNames(),并使用此信息。

    如果接口不存在,你可以恢复到 Type.GetMethods()。

    这也应该处理“动态”类型。

    【讨论】:

    • 如果duck 被声明为dynamic duck,当您执行duck.GetType() 时会发生什么?它返回什么类型?
    • 如果动态对象是 .NET 对象,则获取对象的类型。
    • 我不认为你可以对动态对象进行这样的反射......也许如果它们是常规的 CLR 对象你可以,但你不能使用来自 IronRuby 的对象,例如...... .
    • 这适用于 CLR 对象。如果您正在处理来自完全动态语言的类型,则该语言可能有其自己的机制。但是,根据定义,在无类型对象之上提供类型安全是困难的(非常棘手)。如果您正在处理一个真正无类型的对象,那么您应该使用该语言的类型分派机制,或者将其保留为运行时检查。
    • 您可以将静态 GetMethods() 与 IDynamicMetaObjectProvider 的测试和对 IDynamicMetaObjectProvider.GetMetaObject().GetDynamicMemberNames() 的调用结合起来。
    【解决方案2】:

    我不知道检查对象是否提供特定方法的明确方法。当然,您可以使用反射,但这仅在对象是 .NET 对象时才有效。如果您确定它没有问题,那么如前所述,只需在对象上调用 GetType() 并使用 GetMethod() 进行检查。

    另一方面,正如您自己所说,即使此时进行检查也不能保证稍后对该方法的调用会成功,因此我认为检查是无用的。只是让呼叫在实际发生时失败。也可能是您的检查表明该对象未提供特定方法,但稍后,当您实际调用它时,它确实提供了。

    【讨论】:

      【解决方案3】:

      使用反射检查方法:

      if (duck.GetType().GetMethod("Bar") == null) {
          throw new ArgumentException("duck", "Bad dynamic object");
      }
      

      【讨论】:

      • 这有效,但仅适用于常规 CLR 对象。真正动态的对象可能没有 Bar 方法并且仍然响应调用。
      猜你喜欢
      • 1970-01-01
      • 2011-01-03
      • 2011-02-18
      • 2014-08-18
      • 2011-04-14
      • 2021-04-30
      • 2017-01-01
      • 2023-03-30
      • 1970-01-01
      相关资源
      最近更新 更多