.NET Enterprise Services 为企业应用程序提供重要的基础结构。COM+ 为企业环境中部署的组件编程模型提供服务结构。System.EnterpriseServices命名空间向 .NET 对象提供对 COM+ 服务的访问,COM+ 服务令 .NET Framework 对象更适用于企业应用程序。

服务组件(ServicedComponent)是一种使 COM+ 服务能够用于 .NET Framework的机制。实时 (JIT) 激活、同步、对象池、事务和共享的属性管理都是可以使用的熟知的 COM+ 服务。还有其他 COM+ 服务,如松耦合事件、排队组件 (QC) 和基于角色的安全性,可以使用这些服务来编写灵活的、基于 .Net Framework的应用程序。

1. 可用的COM+服务列表

(1)自动事务处理(Automatic transactions): COM+ 提供的一个服务,用于在设计时配置类,以便在运行时参与事务。COM+ 使您能够为要求事务处理的每一个类指定不同的事务超时。可以使用这一功能解决冲突的超时情况,如强制短时间事务和允许长时间运行的批存储过程。

如果不指定事务超时值,则使用计算机整个系统范围的超时值。事务超时是以秒为单位度量的整数值。下面的示例说明如何将事务超时设置为 10 秒。

[Transaction(TransactionOption.Required, Isolation=TransactionIsolationLevel.Serializable, Timeout=10)]

[ AutoComplete(true/false) ]属性应用于方法,如果方法标明[ AutoComplete(true) ],指定如果事务成功完成应用程序应自动调用ContextUtil.SetComplete()方法,如果异常,则调用ContextUtil.SetAbort()方法。

如果方法标明[ AutoComplete(false) ]或者忽略这一属性(AutoComplete配置前的默认值为false),则需要在程序中手动管理事务,通过调用ContextUtil类的静态方法SetComplete()和SetAbort()来完成。

(2)COM+ BYOT(带来您自己的事务) 功能允许 COM+ 组件将先前存在的 Microsoft 分布式事务处理协调器 (DTC) 或事务 Internet 协议 (TIP) 事务设置为新组件的上下文的事务属性。此功能允许将 COM+ 组件与生存期受事务处理监视器、对象事务服务或数据库管理系统控制的事务关联。BYOT 对于集成由 TIP 协调的事务也有用处。

注意:对于编写业务组件来说,首选的编程模型是自动事务,而不是 BYOT 事务。使用 BYOT 事务时必须谨慎。

(3)补偿资源管理器 (CRM) 是 COM+ 提供的一项服务,使您可以在 Microsoft 分布式事务处理协调器 (DTC) 事务中包括非事务性对象。虽然 CRM 不提供完整资源管理器的功能,但它们却通过恢复日志提供事务性原子性(全有或全无行为)和持久性。

(4)Just-in-time (JIT) activation: COM+ 实时 (JIT) 激活服务允许更好地使用空闲服务器资源。将组件配置为 JIT 激活后,COM+ 可在客户端仍保持对象的当前引用时停用该组件的实例。客户端下次在该对象上调用方法时,COM+ 将“实时地”以对客户端透明的方式重新激活该对象。

注意   对于配置为 JIT 激活的组件,对象首次创建时被激活。

在方法调用返回时,COM+ 停用该对象,但将上下文留在内存中。已停用的对象释放所有资源,包括锁定昂贵的数据存储区。

若要启用 JIT 激活,请将 JustInTimeActivationAttribute 属性应用于从 System.EnterpriseServices.ServicedComponent 派生的类。另外,为确保在方法调用返回时停用对象,有必要设置对象的完成位。对于事务性组件,可将 AutoCompleteAttribute 应用于类或者调用 ContextUtil.SetComplete 或 ContextUtil.SetAbort。对于非事务性组件,则调用 ContextUtil.DeactivateOnReturn。

注意   自动事务处理要求 JIT 激活;因此,为自动事务处理配置类时,隐式启用 JIT 激活。

(5)Loosely coupled events:COM+ 提供的松耦合事件模型支持后期绑定事件或发布服务器和订阅服务器之间的方法调用,同时还支持事件系统。不用反复地轮询服务器,事件系统会在信息可用时通知有关各方。

若要使用此服务,事件类和事件接收必须直接或间接从 System.EnterpriseServices.ServicedComponent 类派生。

(6)对象构造(Object construction):COM+ 对象构造用于从外部指定初始化信息,从而不必在类内指定硬编码配置信息。与对象池一起使用的对象构造函数提供资源分配器的能力,而不必实现完整的资源分配器。

可以这样配置对象构造,即,将 ConstructionEnabledAttribute 属性应用到从 System.EnterpriseServices.ServicedComponent 类派生出来的类。

(7)对象池(Object pooling):COM+ 对象池服务可以减少从头创建每个对象的系统开销。在激活对象时,它从池中提取。在停用对象时,它放回池中,等待下一个请求。

对象池使您能够控制所使用的连接数量,与连接池相反,连接池用来控制达到的最大数量。下面是对象池和连接池之间的重要区别:

  • 创建。使用连接池时,创建在同一线程上进行,因此如果池中没有连接,则代表您创建连接。采用对象池时,池可以决定创建新对象。但是,如果已经达到最大数量,它会给您下一个可用的对象。当需要花费较长时间来创建对象时,这的确是一个重要的行为。但不要长期使用这种方法来创建对象。
  • 最小值和最大值的实施。不在连接池中实施。对象池的最大值在尝试缩放应用程序时很重要。可能需要仅为几个对象而复用成千上万个请求。

[ObjectPooling(Enabled=true, MinPoolSize=2, MaxPoolSize=5, CreationTimeOut=20000)]

(8)专用组件[PrivateComponent]:公用组件可以从其他应用程序中激活,但您可能在应用程序中有多个帮助器组件,这些组件只能从该应用程序内的其他组件调用。在 COM+ 中,可以使用 PrivateComponentAttribute 属性将这些组件标记为专用。专用组件只能由同一应用程序中的其他组件看到和激活。如果调用专用组件的任何类,从进程外调用就会失败,而从进程内调用就会成功。相比之下,如果调用公用组件上的任何类,进程内和进程外调用都会成功。

(9)排队组件(Queued components):COM+ 排队组件服务提供了一种使用 Microsoft 消息队列异步调用和执行组件的便捷方式。不管发送方或接收方的可用性或可访问性如何,都可进行处理。

[ApplicationQueuingAttribute(QueueListenerEnabled = true, MaxListenerThreads =  64 )]

MaxListenerThreads 属性指示并发排队组件侦听器线程的最大数。此值的有效范围是 0 到 1000。对于新创建的应用程序,设置是从当前用于确定侦听器线程的默认数量的算法得到的:16 乘以服务器中的 CPU 数量。此值并不表明任何时候正在运行的线程数量,只是可能的线程的最大数量。在空闲服务器上,可能只有一个线程在运行,直到在队列中出现更多消息为止。然后服务器将按需要创建更多线程,直到它达到 MaxListenerThreads 值。上面的示例将排队组件侦听器线程的最大数量设置为 64。

(10)基于角色的安全性(Role-based security):NET Framework 提供了将托管代码与 COM+ 安全服务集成的机制。此功能依靠与执行代码关联的 Microsoft Windows NT标记作为标识的基础。

注意   .NET Framework 和 COM+ 基于角色的安全性机制是相互独立的,在单个应用程序内只能使用一个机制。

COM+ 安全依靠 Windows NT 帐户和进程/线程模拟。如果托管代码提供身份验证服务,那么在调用任何 COM 对象之前,它必须获得 Windows NT 安全标记并进行模拟。

(11)SOAP 服务 (Only in COM+ 1.5):COM+ SOAP 服务允许采用现有的组件作为 XML Web services 发布。客户端仍可以继续使用以前的方法访问该组件,但该组件也可以使用 WSDL(Web 服务描述语言)和 SOAP 进行访问。

[ApplicationActivation(ActivationOption.Library, SoapVRoot="MyVRoot")]

SoapVRoot 属性用于托管代码时,它使您能够通过 COM+ SOAP 服务公开托管服务组件。配置此属性等效于在包含服务组件的 COM+ 应用程序上启用 SOAP 服务。SoapVRoot 属性包含要作为终结点发布的虚拟根目录的名称。名称是一个简单的字符串(例如,“MyVRoot”),可以在 Web 服务器上作为“http://MyServer/MyVRoot”发布。如果不提供值,SoapVRoot 属性将设置为空。

(12)同步[Synchronization]:同步是执行的逻辑线程,有时称为“活动”。COM+ 同步服务提供在对象之间流动的同步,并在任何给定时间都禁止一个以上的调用方进入组件。同步确定何时线程可以调度对对象的调用。

若要使用自动同步,请将 SynchronizationAttribute 属性应用到从 System.EnterpriseServices.ServicedComponent 派生的类。

******

虽然COM+提供了一大堆Attribute,实际上平时比较常用的Attribute有:Automatic transactions, Object Pooling和Just-in-Time activation。

2. COM+ 应用程序标识

可以通过名称或 GUID 标识现有的 COM+ 目标应用程序。.NET 服务安装工具 (Regsvcs.exe) 提供 /appname: 选项,用于指定应用程序名。

[ assembly: ApplicationName("BankComponent")]

如果将 ApplicationID 属性(或 Guid 属性)应用到程序集,如下面的示例所示,则所有针对应用程序的搜索都基于该 GUID,而不基于应用程序名。

[ assembly: ApplicationName("BankComponent")]

[ assembly: ApplicationID("4fb2d46f-efc8-4643-bcd0-6e5bfa6a174c")]

3. 激活类型

激活类型确定服务组件是在调用方的进程(库)中还是在新进程(服务器)中创建的。可以应用 ApplicationActivationAttribute 属性来指定激活类型。

注意   如果 ApplicationActivationAttribute 属性设置为 Server - [ assembly: ApplicationActivation(ActivationOption.Server)],则在可以使用服务器应用程序之前,必须用 Windows 安装程序将程序集及其所依赖的所有程序集添加到全局程序集缓存 (GAC) 中;否则,应用程序将产生异常。此外,如果 ApplicationActivationAttribute 属性设置为 Server,则服务组件的任何参数都必须标记为 Serializable,或者必须从 MarshalByRefObject 类派生。否则,应用程序将产生异常。

默认设置为:[ assembly: ApplicationActivation(ActivationOption.Library)]

4. 注册服务组件

服务组件由 COM+ 应用程序承载,且必须对该应用程序是可访问的。为了便于访问,服务组件有下面的注册和配置要求:

  • 程序集必须具有强名称。
  • 程序集必须在 Windows 注册表中注册。
  • 类型库定义必须注册并安装到特定的 COM+ 应用程序中。
  • 以编程方式添加的服务必须在 COM+ 目录中配置。

动态注册程序集

部署服务组件的应用程序的最简单方式是采用动态注册,它包括将包含一个或多个服务组件的程序集复制到 COM+ 应用程序的目录中。动态注册的程序集不放在全局程序集缓存中。

注意   放在全局程序集缓存中的程序集要求手动注册。

如果创建了服务器应用程序,则在该应用程序可以使用之前,必须用 Windows 安装程序将程序集及其依赖的所有程序集添加到全局程序集缓存 (GAC) 中;否则,该应用程序将生成异常。

手动注册程序集

.NET Framework SDK 提供 .NET 服务安装工具 (Regsvcs.exe),用于手动注册包含服务组件的程序集。Regsvcs.exe 是一个命令行工具。还可以通过创建 RegistrationHelper 类的实例并使用 InstallAssembly 方法,利用 System.EnterpriseServices.RegistrationHelper 类以编程方式访问这些注册功能。

虽然并不是总这样要求,但手动注册程序集对于设计时测试是有帮助的。与动态注册不同,手动过程能提供有关在执行时遇到的错误的反馈。

5. .Net环境下创建COM+服务组件

可以参考CodeProject.com网站Giles的这篇文章《Creating COM+ Objects using EnterpriseServices in .Net》,在CodeProject.com上评论不错。

关于.Net环境下创建COM+服务组件的例子,大部分都是演示关于多数据库更新的分布式事务控制。实际上,如果采用SQL Server作为Database Server,不管是跨Database,还是跨SQL Server,都可以通过Stored Procedure中的事务控制,或者是ADO.Net的SqlTransaction对象来实现,只是不推荐这样做而已。

******

上述关于COM+/服务组件介绍部分的大量内容来自MSDN Reference 1。

References:

1, MSDN, http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconservicedcomponentoverview.asp

2, Giles, Creating COM+ Objects using EnterpriseServices in .Net, http://www.codeproject.com/csharp/estransactions.asp

05-28 23:31