2016-06-08 160 views
1

鑑於任何Class<?> clazz對象,是否有API獲取EClass的模型實例實現clazz? (即eClass爲其eClass.getInstanceClass().equals(clazz)爲true)從EMF模型實例類獲取EClass

如果我有一個eObject,我可以簡單地叫eObject.eClass()得到EClass。但在我的情況下,我沒有這樣的例子。我只有一個模型實例類,需要關聯的EClass才能撥打EcoreUtil.create(eClass)

+0

你可以舉一個例子,你必須使用它嗎?你從'obj.getClass()'獲得'clazz',其中'obj'是一個'EObject'實例,或者你在代碼中使用'InterfaceName.class'獲得'clazz'(例如:在UML中,'Activity .class')? –

+0

@VincentAranega我使用'InterfaceName.class',因爲我沒有任何'obj'在那一點。它想要提供方法'create(InterfaceName。因爲它可以是類型安全的,並且據我所知,爲了得到一個EClass我需要通過名稱獲得它('ePackage.getEClassifier(「MyClass」)'') )或者我需要使用奇怪的引用'MyPackage.Literals.MY_CLASS',我想避免 – Kapep

+0

好吧。我想我有一個解決方案,然後:)(我正在寫這個)。 –

回答

4

爲了說明答案,我會asume,我們有一個名爲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),除非你explicitally投myinstanceA使用此:

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

你可以瀏覽代碼,也許它可以幫助你。

希望我明白你的問題。

+0

謝謝!它依賴於模型名稱與實例類型名稱相同,但是,對吧?但它應該在大多數情況下工作,並可能會爲我工作。 – Kapep

+1

是的,它依賴於生成的接口名稱與您在'.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()); 
     } 
    } 
}