在C#中使用“动态”来实现访问者模式 [英] Using 'dynamic' in C# to implement Visitor Pattern

查看:309
本文介绍了在C#中使用“动态”来实现访问者模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我在哪里上一系列元素和操作的确切性质进行操作取决于被操作的元件的类型的应用程序。对于封装的原因,这是不恰当的元素来实现该操作;这意味着它不能在元素类型的虚拟方法,因此标准多态性不起作用。我提出一个<一个href="http://stackoverflow.com/questions/10586357/polymorphism-vs-division-of-responsibilities-how-to-avoid-switching-on-type">$p$pvious问题与此相关的,得知这个被称为Visitor模式。

我有previously总是使用 IF / ELSEIF 调度方法,基于对象的类型,然后调用相应的实现来实现这一点。然而,最近我注意到,同样的事情可以使用动态关键字完成,像这样的:

 私人无效ReconcileTips()
{
    的foreach(在_definition.Steps VAR步骤)
    {
        ReconcileTips((动态)步骤);
    }
}

私人无效ReconcileTips(IBulkDispenseDefinition bulkDispense)
{
    bulkDispense.TipType = ReconcileTip(bulkDispense.TipType);
}

私人无效ReconcileTips(ImportScreenDefinition importScreen)
{
    的foreach(VAR用法importScreen.ReagentUsages)
        usage.TipType = ReconcileTip(usage.TipType);
}

私人无效ReconcileTips(BuildScreenDefinition buildScreen)
{
    的foreach(在buildScreen.Functions VAR功能)
        function.TipType = ReconcileTip(function.TipType);
}
 

一个类似的模式也可以使用其他操作平行的对类结构,如对 _definition.Steps 的每个元素创建视图模型。思想是编译器基本上转变到这一相同的 IF / ELSEIF 逻辑我之前写的,救了我的工作。因此,有几个问题:

  1. 是否存在与动态调度,我还没有考虑任何陷阱?我相信这是相当于执行了一系列的如果(x是类型A)DO((类型A)x)的东西... ,但我可能是错的。

  2. 这是真正清洁和更容易理解比长 IF / ELSEIF 的方法?

解决方案
  

是否存在与动态调度,我还没有考虑任何陷阱?我相信这是相当于执行了一系列如果(x是类型A)做((类型A)x)的东西...,但我可能是错的。

主要的疑难杂症是,如果一个类实现多个接口,在你的访问者模式 - 编译器可能会挑一个你想要的,但它可能是不一样的选择,你会做,如果你使用如果(x是类型A) / 否则,如果(x是的TypeB)逻辑,正如你所控制的顺序性检查会。

  

这是真正清洁和更容易理解比一个长,如果/ elseif的方法是什么?

我个人这么认为。这提供了运行时类型确定的很干净,很体面进行调度,而只是工作。难打简单的,短的,干净的code。只要确保(潜在的)处理,你得到的错误类型运行时错误传递的情况下。

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#中使用“动态”来实现访问者模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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