我可以访问无法修改的类结构,如下所示:
Graphics
Circle
Line
etc.
同样,我无法修改!这些都有单独的属性,例如Radius
,FirstPoint
,LastPoint
等,以及一些常见的属性。
我想创建一个接受Graphics
对象的方法,并根据对象的类型运行一个ToJson
方法:
Graphics g = db.GetGraphic(123);
// Console.WriteLine(g.GetType()) prints "Circle"
// Should run some specific implementation for `Circle` type graphics, and
// have an overload for all types including Graphics
ToJson(g);
起初我以为我可以巧妙地重载ToJson
方法:
ToJson(Graphics g) { ... }
ToJson(Circle g) { ... }
ToJson(Line g) { ... }
但这当然每次都会导致通用ToJson(Graphics)
超载。
我确定我可以执行以下操作:
if (g is Circle) ...
if (g is Line) ...
if (g is Graphics) ...
或创建一个Dictionary来降低每种类型的复杂性,但这并不像是做事的最佳方式
我考虑过的
我考虑过是否可以在每个对象周围使用某种通用包装方法(例如new JsonGraphics(g).ToJson()
),但是我不想自己进行任何手动类型检查。
我已经研究了双重调度和访问者模式,但是我不确定它们是否满足我的要求,因为它们看起来像我必须修改这些类(或者也许我只是不完全理解它们),以及显然,)泛型也基本上不在窗口之内,因为它们要求我提前知道这是什么类型的Graphics
对象。
然后有两个问题:
除了使用一些Dictionary或其他类似if (g is Type)
的东西之外,还有其他更好的方法吗?
如果我可以修改类,则模式将如何显示?在这种情况下这是不可能的,但是在可能的情况下,双重派遣/访客是否是最好的选择?
答案 0 :(得分:2)
由于无法修改基类,也无法在将具体类型转换为通用Graphics
类型之前对其进行访问,很遗憾,除了检查运行时类型之外,我认为您无法做任何其他事情Graphics
个对象。
您可以使用switch语句(自C#7.0起),它比您的if
链要干净一些:
switch (g)
{
case Circle circle: ... break;
case Line line: ... break;
default: /* Oh no! */ break;
}
就这样的switch语句,我个人认为使用Dictionary并没有太大优势-两者都可以放在一个独立的方法中(这样可以减少违反的 amount (打开/关闭原理),但开关价格会便宜得多。
您还可以使用dynamic
,这会导致运行时进行后期绑定:
dynamic d = g;
ToJson(d); // Picks the right ToJson overload corresponding to the runtime type of 'd'
...但是,动态具有相当大的运行时成本,通常被认为是气味。