我正在使用EMF模型,需要复制这些模型。我的模型由三个元模型的相互关联的实例组成,其中一个是Ecore本身。到现在为止还挺好。
然而,当涉及复制这些模型时(我按照通常的协议使用EcoreUtil.Copier.copyAll
),我的模型的某些部分不会被复制。具体来说,Ecore实例包含许多EGenericType
实例(因为有引用和属性,这些实例和EGenericType
实例会自动设置以显示其类型)。复制的结果包含所有内容,但EGenericType
。
我已经搜索过高低,并查看了EMF源代码,但无法弄清问题是什么。我查看了EcoreUtil.Copier
的来源,它检查每个结构特征是否可更改而不是派生以决定是否实际复制它。对于EGenericType
的引用,这种情况属实,因此应将其复制为包含引用。
有趣的是,副本的结果包含对象图中所有正确位置的EGenericType
的复制实例。但是,这些并没有映射到复印机中,所以似乎不是通过调用EcoreUtil.Copier.copy
来创建的,而是隐含的。
创建这些内容时的任何想法以及如何让它们显示在复印机地图中?
非常感谢,
斯特芬
答案 0 :(得分:1)
好的,所以我用调试器深入研究了这一点,并认为我现在明白了发生了什么:
基本上,ETypedElement
(包含类型和泛型类型)与合同有点松散:eType
和eGenericType
都没有标记为派生,但取决于具体情况,他们中的一个将来自另一个。
具体而言,如果您设置eType
的{{1}},则会隐式创建新的ETypedElement
。同样,如果您设置eGenericType
,则会隐式将eGenericType
设置为此泛型类型的擦除。
不幸的是,当eType
明确设置了EcoreUtil.Copier
时,此行为会混淆ETypedElement
。在这种情况下,会发生以下情况:
eType
创建EcoreUtil.Copier.copy
的新实例,然后开始复制其所有功能。
当它到达ETypedElement
功能时,此时不会复制它,因为eType
不是包含引用(原因很明显)。
接下来是eType
,这是一个遏制参考。但是,它首先要检查是否在原始eGenericType
中设置了此项。对于ETypedElement
和eGenericType
,此检查已经过自定义,以确保只有两个中的一个实际返回eType
。因此,对于我们的true
,ETypedElement
返回isSetEType()
和true
会返回isSetEGenericType()
。因此,true
决定无需复制和移动。
当copyContainment()
或copy()
返回时,既没有为新创建的对象设置copyAll()
也eType
。我们现在致电eGenericType
。
这最终将尝试复制copyReferences()
引用(请记住,这被标记为不是包含引用)。 eType
返回isSetType()
,因此true
会继续并复制类型信息。然后,复制对象中copyReference()
的setter会创建eType
的新实例,但EGenericType
永远不会看到它。
因此,如果我想让原始EcoreUtil.Copier
实例及其副本显示在副本地图中,我需要子类EGenericType
并覆盖EcoreUtil.Copier
或{ {1}}处理这种特殊情况。