使用 C# 4 对动态对象进行鸭子类型测试
我想要一个使用动态对象的 C# 简单鸭子类型示例。在我看来,动态对象应该具有 HasValue/HasProperty/HasMethod 方法,并在尝试运行它之前使用单个字符串参数来表示您要查找的值、属性或方法的名称。我试图避免 try/catch 块,并尽可能避免更深层次的反思。这似乎是动态语言(JS、Ruby、Python 等)中鸭子类型的常见做法,即在尝试使用属性/方法之前测试它,然后回退到默认值,或抛出受控异常。下面的例子基本上就是我想要完成的。
如果上述方法不存在,是否有人有预制的动态扩展方法可以做到这一点?
示例:在 JavaScript 中,我可以相当轻松地测试对象上的方法。
//JavaScript
function quack(duck) {
if (duck && typeof duck.quack === "function") {
return duck.quack();
}
return null; //nothing to return, not a duck
}
我如何在 C# 中做同样的事情?
//C# 4
dynamic Quack(dynamic duck)
{
//how do I test that the duck is not null,
//and has a quack method?
//if it doesn't quack, return null
}
I'm wanting to have a simple duck typing example in C# using dynamic objects. It would seem to me, that a dynamic object should have HasValue/HasProperty/HasMethod methods with a single string parameter for the name of the value, property, or method you are looking for before trying to run against it. I'm trying to avoid try/catch blocks, and deeper reflection if possible. It just seems to be a common practice for duck typing in dynamic languages (JS, Ruby, Python etc.) that is to test for a property/method before trying to use it, then falling back to a default, or throwing a controlled exception. The example below is basically what I want to accomplish.
If the methods described above don't exist, does anyone have premade extension methods for dynamic that will do this?
Example: In JavaScript I can test for a method on an object fairly easily.
//JavaScript
function quack(duck) {
if (duck && typeof duck.quack === "function") {
return duck.quack();
}
return null; //nothing to return, not a duck
}
How would I do the same in C#?
//C# 4
dynamic Quack(dynamic duck)
{
//how do I test that the duck is not null,
//and has a quack method?
//if it doesn't quack, return null
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您可以控制将动态使用的所有对象类型,则另一种选择是强制它们从
DynamicObject
类的子类继承,该子类被定制为在方法执行以下操作时不会失败:调用不存在:一个快速而肮脏的版本将如下所示:
然后您可以执行以下操作:
您的输出将是:
编辑:我应该注意,如果您能够使用此方法,这只是冰山一角并在
DynamicObject
上构建。如果您愿意,您可以编写类似bool HasMember(string memberName)
的方法。If you have control over all of the object types that you will be using dynamically, another option would be to force them to inherit from a subclass of the
DynamicObject
class that is tailored to not fail when a method that does not exist is invoked:A quick and dirty version would look like this:
You could then do the following:
And your output would be:
Edit: I should note that this is the tip of the iceberg if you are able to use this approach and build on
DynamicObject
. You could write methods likebool HasMember(string memberName)
if you so desired.试试这个:
或者这个(仅使用动态):
Try this:
Or this (uses only dynamic):
为每个 IDynamicMetaObjectProvider 实现 HasProperty 方法,而不抛出 RuntimeBinderException。
Implementation of the HasProperty method for every IDynamicMetaObjectProvider WITHOUT throwing RuntimeBinderException.
impromptu-interface 似乎是一个不错的动态对象接口映射器...它有点多工作比我希望的要好,但似乎是所提供示例的最干净的实现...保持西蒙的答案正确,因为它仍然最接近我想要的,但即兴接口方法非常好。
impromptu-interface seems to be a nice Interface mapper for dynamic objects... It's a bit more work than I was hoping for, but seems to be the cleanest implementation of the examples presented... Keeping Simon's answer as correct, since it is still the closest to what I wanted, but the Impromptu interface methods are really nice.
最短的路径是调用它,并在该方法不存在时处理异常。我来自Python,这种方法在鸭子打字中很常见,但我不知道它是否在C#4中广泛使用......
我没有测试过自己,因为我的机器上没有VC 2010
The shortest path would be to invoke it, and handle the exception if the method does not exist. I come from Python where such method is common in duck-typing, but I don't know if it is widely used in C#4...
I haven't tested myself since I don't have VC 2010 on my machine
在这里没有看到正确的答案,MS 现在提供了一个转换为字典的示例
Have not see a correct answer here, MS provides an example now with casting to a dictionary