如何保持域和表示对象之间的对应关系
Posted
技术标签:
【中文标题】如何保持域和表示对象之间的对应关系【英文标题】:How to keep correspondence between Domain and Presentation objects 【发布时间】:2020-12-27 13:19:11 【问题描述】:这个问题让我困惑了一段时间。当我与 Presentation 中的对象交互时,如何找出这与哪个 Domain/Business 对象相关?
我的 域/业务 中有 Shape 类,我使用 WPF 在屏幕上绘制这些 Shapes(Presentation)。例如,我的 Domain 中有一个名为 LineShape
的类,然后我使用 System.Windows.Shapes.Line
在 WPF 中绘制它。
现在这是我的问题,我如何保持领域层和业务层中的对象之间的对应关系。假设用户在 WPF 中单击特定的System.Windows.Shapes.Line
,UI 触发一个事件并给我选择的System.Windows.Shapes.Line
,我现在如何识别我的域中选择的System.Windows.Shapes.Line
代表哪个LineShape
?
我曾想过一些方法,但它们看起来并不优雅,尤其是对于更大更复杂的对象模型。
使用字典来保存 Presentation 和 Domain 对象之间的对应关系。在这种方法中,当用户在 UI 中选择一个System.Windows.Shapes.Line
时,我可以在字典中的 domain 中查找对应的LineShape
。
对 Presentations 和 Domain 中的对象都使用 Id。这听起来有点奇怪,因为据我所知,我们不应该对 DDD 中的每个对象都使用 Id,而只是对实体使用。
这里有什么可以遵循的最佳实践吗?
【问题讨论】:
您将通过 ItemsControl(或 ListBox 等派生控件)进行绘图,它的 ItemsSource 属性绑定到域对象的集合。表示对象将由 DataTemplates 创建,或者由它们的 DataType 自动选择,或者由 ItemsControl ItemTemplate 或 ItemTemplateSelector 创建。就像例如这个:***.com/a/40190793/1136211 @Clemens 谢谢Clemens,我也想到了那个,使它类似于显示字符串列表。当然,我上面提供的示例已针对该问题进行了简化。在更复杂的情况下,我无法绑定到 ItemsSource,例如图形 API 可能不同于 WPF,它不允许 ItemsSource。或者在某些情况下,DTO 介于表示和域之间。这些案例怎么办?那么我怎么知道现在在我的 ItemsSource 中的 DTO 属于哪个域对象?谢谢你。 @Clemens 在您提供的链接中,ShapeData 如何链接到 Domain 中的实际 Shape 类?假设用户在 Presentation 中选择了一个 Shape 并将其删除。现在从您的方法中,我知道它对应于哪个 ShapeData,但是我怎么知道这个 ShapeData 链接到域中的哪个形状? ShapeData 是否应该再次引用域中的实际形状?还是有身份证?还是...? “ShapeData 是否应该再次引用 Domain 中的实际 Shape?”- 是的,这是视图模型和模型之间的常用引用。 @Clemens 感谢您的澄清。如果 ViewModel 和 Model 之间存在 DTO,那么 ViewModel 是否应该引用 DTO,然后这些 DTO 是否引用 Model?这部分对我来说似乎很奇怪,因为我没有看到 DTO 引用模型的任何地方。那我们如何找到链接呢? 【参考方案1】:对 Presentations 和 Domain 中的对象都使用 Id。这听起来 对我来说有点奇怪,因为据我所知,我们不应该 为 DDD 中的每个对象使用 Id,仅用于实体。
也许您会查看地址而不是 ID。甚至必须以某种方式解决值,以便可以替换它们。这样的地址可能是类属性的名称、数组的索引等。
如果您将整个绘图视为形状值的集合,那么您始终可以使用形状的索引作为地址,从而允许替换集合中的特定形状值。
但是,请注意,该地址仅在您使用预期的绘图版本时才有效。
此外,您还可以使用所有形状属性的组合来识别要修改的给定形状。如果你有两个相同的形状(相同的形状、位置、图层等),你重新塑造哪个重要吗?最终的图纸看起来完全一样。
最后,如果将形状建模为实体并赋予它们一个 ID 让您的生活更轻松,那么即使您可能不关心特定形状的整个生命周期,这也许也是正确的模型。
最后,请注意,如果形状是值,那么您不可能在视图模型中保留对它们的引用,因为值是不可变的。此外,如果形状是实体,但绘图是聚合根,则形状实体不应在根之外访问。因此,如果它是 AR,那么在视图模型中引用域的 Shape 很可能才有意义(除非您违反可见性规则,但仍然通过根处理的事件强制执行不变量)。另请注意,如果您的域模型位于另一层,则地址/ID 引用可能是唯一的选择。
【讨论】:
【参考方案2】:你问的问题有点笼统,所以我会给出我认为正确但普遍的答案。
在 WPF 中,屏幕控件将有一个 DataContext。 DataContext一般来说应该是你想要获取的对象。
无论您使用什么方法填充所有屏幕控件,都应该或多或少出现这种情况。
它可能适合您的程序来创建特殊的视图模型类,它们在您的“本机”数据对象之间建立桥梁,在这种情况下,这些视图模型类将被设置为 DataContext 对象。如果您不需要视图模型,则本机数据对象将扮演该角色。
如果您正在使用事件,那么在事件的代码隐藏中,您可以直接访问 DataContext 属性,将其转换为预期的类型,然后就可以了。
如果您使用命令,那么通常它们首先是视图模型对象的一部分,因此它们可以直接作用于拥有它们的对象。
【讨论】:
以上是关于如何保持域和表示对象之间的对应关系的主要内容,如果未能解决你的问题,请参考以下文章
CoreData - 如何使对象在不同的线程/上下文中保持最新?
如何在 AJAX 调用之间保持 PHP 对象处于活动状态(或在内存中)