查看文章 |
Posted on 2005-07-06 09:37 追风逐云.NET 阅读(222) 评论(0) 编辑 收藏 引用 网摘 Attribute在拦截机制上的应用 从这一节开始我们讨论Attribute的高级应用,为此我准备了一个实际的例子:我们有一个订单处理系统,当一份订单提交的时候,系统检查库 存,如果库存存量满足订单的数量,系统记录订单处理记录,然后更新库存,如果库存存量低于订单的数量,系统做相应的记录,同时向库存 管理员发送邮件。为了方便演示,我们对例子进行了简化: //Inventory.cs namespace NiwalkerDemo private Hashtable inventory=new Hashtable(); public bool Checkout(string product, int quantity) //Logbook.cs namespace NiwalkerDemo //Order.cs namespace NiwalkerDemo
下面是调用程序: //AppMain.cs using System; namespace NiwalkerDemo
(客户总是经常改变他们的需求),比如库存检查的规则不是单一的检查产品的数量,还要检查产品是否被预订的多种情况,那么你需要改变 Inventory的代码,同时还要修改Order中的代码,我们的例子只是一个简单的商务逻辑,实际的情况比这个要复杂的多。问题在于Order对象同 其他的对象之间是紧耦合的,从OOP的观点出发,这样的设计是有问题的,如果你写出这样的程序,至少不会在我的团队里面被Pass. 你说了:“No problem! 我们可以把商务逻辑抽出来放到一个专门设计的用来处理事务的对象中。”嗯,好主意,如果你是这么想的,或许我 还可以给你一个提议,使用Observer Design Pattern(观察者设计模式):你可以使用delegate,在Order对象中定义一个BeforeSubmit和 AfterSubmit事件,然后创建一个对象链表,将相关的对象插入到这个链表中,这样就可以实现对Order提交事件的拦截,在Order提交之前和提 交之后自动进行必要的事务处理。如果你感兴趣的话,你可以自己动手来编写这样的一个代码,或许还要考虑在分布式环境中(Order和 Inventory不在一个地方)如何处理对象之间的交互问题。 幸运的是,.NET Framework中提供了实现这种技术的支持。在.NET Framework中的对象Remoting和组件服务中,有一个重要的拦截机制,在对 象Remoting中,不同的应用程序之间的对象的交互需要穿越他们的域边界,每一个应用域也可以细分为多个Context(上下文环境),每一个应 用域也至少有一个默认的Context,即使在同一个应用域,也存在穿越不同Context的问题。NET的组件服务发展了COM+的组件服务,它使用 Context Attribute来实现象COM+一样的拦截功能。通过对调用对象的拦截,我们可以对一个方法的调用进行前处理和后处理,同时也解决了上 述的跨越边界的问题。 需要提醒你,如果你在MSDN文档查ContextAttribute,我可以保证你得不到任何有助于了解ContextAttribute的资料,你看到的将是这么一句 话:“This type supports the .NET Framework infrastructure and is not intended to be used directly from your code.”——“本 类型支持.NET Framework基础结构,它不打算直接用于你的代码。”不过,在msdn站点,你可以看到一些有关这方面的资料(见文章后面的参 考链接)。 下面我们介绍有关的几个类和一些概念,首先是: ContextAttribute类 ContextAttribute派生自Attribute,同时它还实现了IContextAttribute和IContextProperty接口。所有自定义的ContextAttribute必须从这个 类派生。 公共属性: 公共方法: ContextBoundObject类 实现被拦截的类,需要从ContextBoundObject类派生,这个类的对象通过Attribute来指定它所在Context,凡是进入该Context的调用都可以被 拦截。该类从MarshalByRefObject派生。 以下是涉及到的接口: IMessage:定义了被传送的消息的实现。一个消息必须实现这个接口。 IMessageSink:定义了消息接收器的接口,一个消息接收器必须实现这个接口。 参考文章:Decouple Components by Injecting Custom Services into Your Object's Interception Chain |