《EMF:A Developer's Guide》读书笔记第二章 :EMF简介(下)

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,那么还有另外的知识需要学习。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值