在C#中使用'dynamic'来实现Visitor Pattern [英] Using 'dynamic' in C# to implement Visitor Pattern

查看:170
本文介绍了在C#中使用'dynamic'来实现Visitor Pattern的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,我正在对一系列元素执行操作,操作的确切性质取决于正在操作的元素的类型。为了封装的原因,元素不适合实现该操作;这意味着它不能是元素类型上的虚拟方法,因此标准多态不起作用。我提出了一个以前的问题相关对此,被告知这被称为访客模式。



我以前一直使用如果/ elseif dispatcher方法基于对象的类型,然后调用适当的实现。最近,我注意到,同样的事情可能会使用动态关键字,如下所示:

  private void ReconcileTips()
{
foreach(var step in _definition.Steps)
{
ReconcileTips((dynamic)step);
}
}

private void ReconcileTips(IBulkDispenseDefinition bulkDispense)
{
bulkDispense.TipType = ReconcileTip(bulkDispense.TipType);
}

private void ReconcileTips(ImportScreenDefinition importScreen)
{
foreach(importScreen.ReagentUsages中的var usage)
usage.TipType = ReconcileTip(usage。 TipType);
}

private void ReconcileTips(BuildScreenDefinition buildScreen)
{
foreach(buildScreen.Functions中的var函数)
function.TipType = ReconcileTip(function。 TipType);
}

类似的模式可以用于与类结构并行的其他操作,如为 _definition.Steps 的每个元素创建视图模型。想到的是,编译器基本上将它转换成与我之前写的逻辑相同的,从而节省了我的努力。所以,几个问题:


  1. 有没有我没有考虑的动态调度的问题?我相信这相当于执行一系列 if(x是TypeA)Do((TypeA)x)else ... ,但我可能是错误的。 >


  2. 如果/ elseif 方法,这是否比较长的更简洁易懂?


解决方案


有没有任何疑问与动态调度,我避风港'不考虑我相信这相当于执行一系列if(x是TypeA)Do((TypeA)x)else ...,但我可能是错的。


如果一个类型在访问者模式中实现了多个接口,那么主要的getcha是 - 编译器可能会选择一个你想要的,但是如果你使用 if(x为TypeA) / else if(x为TypeB)逻辑,因为您可以控制订单检查发生。


这是比一个长的if / elseif方法更清洁和更容易理解吗?


我个人认为如此。这提供了由运行时类型确定的非常干净,相当正式的执行调度,并且正常工作。很难打败简单,简短,干净的代码。只需确保(潜在地)处理从传入的错误类型中得到运行时错误的情况。


I have an application where I am performing an operation on a series of elements and the exact nature of the operation depends on the type of the element being operated upon. For reasons of encapsulation, it's not appropriate for the element to implement the operation; this means it can't be a virtual method on the element type and so 'standard' polymorphism doesn't work. I posed a previous question related to this and was informed that this was known as the Visitor Pattern.

I had previously always implemented this using an if/elseif dispatcher method based on the type of the object, then calling an appropriate implementation. Recently, however, I noticed that the same thing could be accomplishing using the dynamic keyword, like this:

private void ReconcileTips()
{
    foreach (var step in _definition.Steps)
    {
        ReconcileTips((dynamic)step);
    }
}

private void ReconcileTips(IBulkDispenseDefinition bulkDispense)
{
    bulkDispense.TipType = ReconcileTip(bulkDispense.TipType);
}

private void ReconcileTips(ImportScreenDefinition importScreen)
{
    foreach (var usage in importScreen.ReagentUsages)
        usage.TipType = ReconcileTip(usage.TipType);
}

private void ReconcileTips(BuildScreenDefinition buildScreen)
{
    foreach (var function in buildScreen.Functions)
        function.TipType = ReconcileTip(function.TipType);
}

A similar pattern could be used for other operations parallel to the class structure, like creating view models for each element of _definition.Steps. The thought is that the compiler basically transforms this into the same if/elseif logic I wrote before, saving me the effort. So, a few questions:

  1. Are there any gotchas with the dynamic dispatching that I haven't considered? I believe this is equivalent to performing a series of if (x is TypeA) Do((TypeA)x) else..., but I could be wrong.

  2. Is this actually cleaner and easier to understand than a long if/elseif method?

解决方案

Are there any gotchas with the dynamic dispatching that I haven't considered? I believe this is equivalent to performing a series of if (x is TypeA) Do((TypeA)x) else..., but I could be wrong.

The main gotcha would be if a type implements more than one interface in your visitor pattern - the compiler will probably pick the one you want, but it may not be the same choice you'd make if you use if (x is TypeA)/else if (x is TypeB) logic, as you'd control the order the checks occur.

Is this actually cleaner and easier to understand than a long if/elseif method?

I personally think so. This provides a very clean, fairly decently performing dispatch determined by the runtime type, and "just works." Hard to beat simple, short, clean code. Just make sure to (potentially) handle the case where you get a runtime error from the wrong type being passed in.

这篇关于在C#中使用'dynamic'来实现Visitor Pattern的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆