xiaoxiaoleemin

天道酬勤,小小加油
posts - 19, comments - 12, trackbacks - 0, articles - 0
    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,那么还有另外的知识需要学习。

Feedback

# re: 《EMF:A Developer's Guide》读书笔记第二章 :EMF简介(下)  回复  更多评论   

2007-05-04 22:16 by lunzi
嗯,不错!

只有注册用户登录后才能发表评论。


网站导航: