【问题标题】:Get EClass from EMF model instance class从 EMF 模型实例类中获取 EClass
【发布时间】:2017-07-06 17:59:15
【问题描述】:

给定任何Class<?> clazz 对象,是否有API 可以获取模型实例实现clazzEClass? (即eClasseClass.getInstanceClass().equals(clazz) 为真)

如果我有eObject,我可以简单地调用eObject.eClass() 来获取EClass。但就我而言,我没有这样的例子。我只有一个模型实例类,需要关联的EClass 来调用EcoreUtil.create(eClass)

【问题讨论】:

  • 你能举一个你必须使用它的例子吗?您是从obj.getClass() 获得clazz,其中objEObject 实例,还是在代码中使用InterfaceName.class 获得clazz(例如:在UML 中,Activity.class)?
  • @VincentAranega 我使用InterfaceName.class,因为那时我没有任何obj。它想提供方法create(InterfaceName.class) 作为create(eClass) 的替代方法,因为它可以是类型安全的,而且据我所知,要获得EClass,我需要通过名称(ePackage.getEClassifier("MyClass"))获取它,或者我会需要使用我想避免的对 MyPackage.Literals.MY_CLASS 的奇怪引用
  • 好吧好吧。我想我有一个解决方案给你:)(我正在写下来)。

标签: java emf


【解决方案1】:

为了说明答案,我假设我们有一个名为Foo 的元模型,如您之前的答案,关联的包是FooPackage,关联的工厂是FooFactory。在这个元模型中,我假设我们有 AB,它们是 EClass

为了获得关联的EClassA.class,你可以使用这个:

String aName = A.class.getSimpleName();
EClassifier classif = FooPackage.eInstance.getEClassifier(aName);
if (classif != null && classif instanceof EClass) {
  // At this point, you have the right EClass, 
  // you can now create an instance using the factory
  EObject myinstance = FooFactory.eInstance.create((EClass)classif);
}

之后,您将需要处理动态实例(您的 EObject),除非您使用以下命令将myinstance 显式转换为A

A instance = (A) myinstance;
// or 
A instance = A.class.cast(myinstance);

如果你把所有这些都放在一个方法中,它可能看起来像这样:

public static <T> T create(java.lang.Class<T> clazz) {
  String iName = clazz.getSimpleName();
  EClassif classif = FooPackage.eInstance.getEClassifier(iName);
  if (classif != null && classif instanceof EClass) {
    return clazz.cast(FooFactory.eInstance.create((EClass)classif));
  }
  return null; // or throw exception, clazz not found or stuff like that
}

请注意,此时,您必须确保您将尝试创建的接口 (A.class) 确实是 EClass 并且不是抽象的,否则会引发异常。

为了处理这种东西,几个月前我开始编写一种库:https://github.com/aranega/dynemf

它还没有完全记录,但你可以做这样的事情:

EPackageWrapper mymm = ePackage(FooPackage.eINSTANCE);
mymm.create(A.class)
  .set("name", "MyAInstance")
  .set("bRels", mymm.create(B.class)
                  .set("name", "MyB1"));

你可以浏览一下代码,或许对你有帮助。

希望我能正确理解您的问题。

【讨论】:

  • 谢谢!它依赖于模型名称与实例类型名称相同,对吧?但它应该适用于大多数情况,并且可能对我有用。
  • 是的,它依赖于生成的接口名称与您在.ecore 中建模的名称完全相同这一事实。 EPackage 上的 .getEClassifier(name) 是 EMF API 的一部分,通常用于处理动态实例(无需从 .ecore 生成 Java 代码)。但是,这些“动态自反”方法比生成的对应方法要慢。
【解决方案2】:

我找不到任何 API。 EClass 与其实例类之间的关系是由生成的初始化方法设置的,但没有任何反向映射。这样做的原因似乎是没有一对一的关系,因为多个模型元素可以使用同一个实例接口。

如果您确定每个类都使用不同的接口,则可以迭代所有 EClassifiers 并自己构建映射。

Map<Class<?>, EClass> eClasses = new HashMap<>();
for (final EClassifier eClassifier : FooPackage.eINSTANCE.getEClassifiers()) {
    if (eClassifier instanceof EClass) {
        if(eClasses.put(eClassifier.getInstanceClass(), (EClass) eClassifier) != null) {
            throw new RuntimeException(
                 "Failed to create distinct instance class to EClass mapping for "
                 + Classifier.getInstanceClass());
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-01-12
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 2017-09-18
    • 2014-05-07
    相关资源
    最近更新 更多