在C#中使用“dynamic”来实现访问者模式

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

我以前总是使用基于对象类型的if/elseif调度程序方法实现它,然后调用适当的实现。 然而,最近,我注意到同样的事情可能是使用dynamic关键字完成,如下所示:

 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); } 

类似的模式可以用于与类结构并行的其他操作,例如为_definition.Steps每个元素创建视图模型。 我们的想法是,编译器基本上将其转换为我之前编写的if/elseif逻辑,从而节省了我的工作量。 那么,有几个问题:

  1. 动态调度是否有任何陷阱我没有考虑过? 我相信这相当于执行一系列if (x is TypeA) Do((TypeA)x) else... ,但我可能错了。

  2. 这是否比if/elseif方法更干净,更容易理解?

动态调度是否有任何陷阱我没有考虑过? 我相信这相当于执行一系列if(x是TypeA)Do((TypeA)x)else …,但我可能错了。

主要的问题是,如果一个类型在访问者模式中实现了多个接口 – 编译器可能会选择你想要的那个,但是如果你使用if (x is TypeA) /它可能不是你做的那个选择else if (x is TypeB)逻辑,因为你控制了检查发生的顺序。

这是否比if / elseif方法更干净,更容易理解?

我个人这么认为。 这提供了一个非常干净,相当不错的执行调度,由运行时类型确定,并且“正常工作”。 难以击败简单,简洁,干净的代码。 只需确保(可能)处理从传入的错误类型中获得运行时错误的情况。

是的,我正在考虑这种方法,但决定采用更传统的方法。 我从一个接口中派生每个访问者,该接口具有我想要为其实现操作的每种类型的访问方法。

如果您想要作为访问者实现许多不同的操作,例如。 保存和加载操作,您可能希望将来添加更多; 使用动态方法,如果忘记为需要处理的其中一种类型实现操作,则不会出现编译错误。 您只会发现程序在运行时崩溃和烧毁的时间。

我想在编译时确保已经为所有可能的类型实现了任何操作。