有没有C#等价于Ruby的`respond_to?`?
我正在写一个简单的包装,以“鸭”一个dynamic
对象与已知的接口:有没有C#等价于Ruby的`respond_to?`?
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中的动态对象来测试它?
(我知道,即使有这个检查栏调用可能失败以后,因为duck
的动态性质让它停止响应方法以后。)
你可以检查对象上可用的方法在施工时使用反射进行包裹。
只需调用接口上的Type.GetMethods()并传入其中的类型,并确保存在适当的方法。
编辑:
至于建议的itowlson,对于处理动态类型,以及一个选项。如果检查传递对象上是否存在IDynamicMetaObjectProvider接口,则可以调用IDynamicMetaObjectProvider.GetMetaObject()。 GetDynamicMemberNames(),并使用此信息。
如果界面不存在,则可以恢复为Type.GetMethods()。
这也应该处理“动态”类型。
使用反射来检查方法:
if (duck.GetType().GetMethod("Bar") == null) {
throw new ArgumentException("duck", "Bad dynamic object");
}
这可行,但只适用于常规的CLR对象。真正的动态对象可能没有Bar方法,并且仍然响应该呼叫。 – 2009-12-09 23:16:03
我不知道一个明确的方法来检查对象提供了具体方法。当然,你可以使用反射,但只有当对象是.NET对象时才有效。如果你确定这是事实,而不是像前面所说的那样,没问题,只需在对象上调用GetType()并使用GetMethod()进行检查。另一方面,正如你自己所说的,即使在这一点上的支票也不能保证后面的方法调用会成功,所以我认为支票是无用的。实际上只是让通话失败。也可能是你的支票说对象没有提供一个特定的方法,但后来,当你实际调用它时,它确实会这样做。
当您执行'duck.GetType()'时,会发生什么?如果'duck'被声明为'dynamic duck'?它返回什么类型? – dtb 2009-12-09 23:12:04
如果动态对象是一个.NET对象,您将获得该对象的类型。 – 2009-12-09 23:12:07
我不认为你可以在动态对象上做类似的反射...也许如果它们是常规的CLR对象,但你不能使用来自IronRuby的对象,例如... – 2009-12-09 23:12:34