EMF Framework提供了模型變化通知、持久化支持、操縱EMF對象的反射API等功能來幫助用戶提高工作效率,下面分別詳細介紹一下。
1.Notification and Adapter EMF生成的每一個類還是一個Notifier類型,因此當它的屬性或者引用改變的時候可以發出通知。這是一個很重要的性質,通過監聽EObject的變化可以及時地更新視圖或者與之相關聯的對象。EMF中的Notification Observer(Listener)叫做Adapter,它除了監聽事件以外,還可以擴展其它行為(extend behavior)等。一個Adapter可以通過如下的方式添加到任何一個EObject對象上(比如PurchaseOrder):
Adapter poObserver = 
aPurchaseOrder.eAdapters().add(poObserver);
然后,當aPurchaseOrder的狀態發生變化時(比如setBillTo方法發生了),poObserver的notifyChanged()方法會被調用。
EContentAdapter,可以添加到一個根元素,一個資源或者一個resource set,它可以監聽這些元素的任何子元素的狀態變化.
Adapter在實現behavior extension(比如不通過繼承來實現某個接口的功能)的功能時,是通過AdapterFactory來完成的。比如:
POAdapter adapter = (POAdapter)somePOAdaterFactory.adapt(someObject,POAdapter.class);
這樣,POAdapter類型的adapter對象被添加到了對象someObject上。
2.Object Persistence EMF對任何model的默認的序列化方式是XMI。有兩個跟序列化相關的函數:eContainer()和eResource().下面通過例子來看這兩個方法的作用:
PurchaseOrder order = POFactory.eINSTANCE.createPurchaseOrder();
order.setBillTo("123 Maple Street");
Item item = POFactory.eINSTANCE.createItem();
item.setProductName("Apples");
item.setPrice(0.45);
item.setQuantity(20);
order.getItems.add(item);
這里PurchaseOrder和Item分別是模型中代表訂單和訂單項的類。這時如果調用item.eContainer()會返回order對象。但是如果調用order.eContainer()則會返回null,因為它沒有被包含在任何元素里邊。這時order和item的eResource()方法都會返回null。
為了序列化這些對象,我們應該把它們加入到一個Resource里邊。Resource是一個代表吳立存儲位置(如文件)的接口。我們只需要把根元素加入到Resource中即可。
Resource resource =
;
resource.getContents().add(order);
這時order和item的eResource()方法都會返回resource對象,其中item是通過order加入到resource中去的。這時調用resource.save(null)后兩個對象就保存下來了。
但是,如何取得resource呢?可以借助于EMF中的ResourceSet, 它是創建Resource的工廠,就是一系列resource的集合。
ResourceSet resourceSet = new ResourceSetImpl();
URI fileURI = URI.createFileURI(new File("mypo.xml").getAbsolutePath());
Resource resource = resourceSet.createResource(fileURI);
resource.getContents().add(order);
resource.save(null);
保存完成之后,如何讀取呢?
PurchaseOrder order = (PurchaseOrder)resource.getContents().get(0);
ResourceSet還支持跨文檔的引用(cross-document reference),當遇到跨文檔的引用時,先用proxy對象來代替實際的對象,當第一次真正使用這個對象的時候才resolve成真正的對象。Proxy是一個關于目標類的一個未初始化的對象,但是它擁有實際對象的URI。
3.The Reflective EObject API
EObject defines a generic,reflective API for manipulating instances.
EClass orderClass = POPackage.eINSTANCE.getPurchaseOrder();
EAttribute shipToAttribute = POPackage.eINSTANCE.getPurchaseOrder_shipTo();
orderClass.eSet(shipToAttribute, "123 street");
String shipTo = orderClass.eGet(shipToAttribute);
上面調用orderClass的eSet和eGet方法比直接調用order的setShipTo()和getShipTo()效率要低一些,因為它要switch做一些條件判斷,但是它的優點是open up the model for completely generic access.EMF.Edit中的AddCommand,SetCommand等通用的命令就是通過這種方式實現的。
4.Dynamic EMF
在沒有生成模型中各個類的代碼之前,我們也可以使用他們的對象,如下:
EPackage package = EcoreFactory.eINSTANCE.createEPackage();
EClass orderClass = EcoreFactory.eINSTANCE.createEClass();
orderClass.setName("PurchaseOrder");
package.getEClassifiers().add(orderClass);
EClass itemClass = EcoreFactory.eINSTANCE.createEClass();
itemClass.setName("Item");
package.getEClassifiers().add(itemClass);
EAttribute shipToAttribute = EcoreFactory.eINSTANCE.createAttribute();
shipToAttribute.setName("shipTo");
shipToAttribute.setEType(EcorePackage.eINSTANCE.getEString());
orderClass.getEAttributes().add(shipToAttribute);
...
接下來,我們可以這樣初始化這些類的對象:
EFactory factory = package.getEFactoryInstance();
EObject order = factory.create(orderClass);
order.eSet(shipToAttribute, “123 street");
至此,EMF的基本知識就介紹完了,如果你只是需要EMF產生的Model Code,那么需要學習的東西就這么多了。如果你還需要EMF產生的Edit Code和Editor Code,那么還有另外的知識需要學習。