是否有一个C#等同于Ruby的`respond_to?`?

时间:2009-12-09 23:06:53

标签: c# dynamic

我正在编写一个简单的包装器,以便针对已知接口“绑定”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的动态特性使其稍后停止响应方法。)

3 个答案:

答案 0 :(得分:4)

您可以在施工时检查使用Reflection包裹的对象上的可用方法。

只需在界面上调用Type.GetMethods()和传入的类型,并确保存在适当的方法。


编辑:

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

如果界面不存在,您可以恢复为Type.GetMethods()。

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

答案 1 :(得分:1)

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

另一方面,正如你自己所说,即使是在这一点检查也不能保证对方法的调用将在以后成功,所以我认为检查是没用的。只是让呼叫在实际发生时失败。也可能是你的检查表明对象没有提供特定的方法,但是稍后,当你真正调用它时,它确实会这样做。

答案 2 :(得分:0)

使用反射来检查方法:

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