« | August 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | | |
|
统计 |
blog名称:小雨 日志总数:262 评论数量:1273 留言数量:15 访问次数:4666341 建立时间:2005年1月8日 |
| 
|
W3CHINA Blog首页 管理页面 写新日志 退出
[知识积累]在 .NET 中使用 COM+ 服务 |
http://www.microsoft.com/china/MSDN/library/archives/library/dndotnet/html/COMservnet.asp
在 .NET 中使用 COM+ 服务
升级到 Microsoft .NET Tim McCarthy - InterKnowlogyPaul D. Sheriff - PDSA, Inc. 2002 年 2 月
摘要:将新的 Microsoft .NET 组件添加到现有的 COM 和 COM+ 应用程序中,它们将协同工作;如果您需要开发能够参与事务、利用基于角色的安全性或者与队列交互的 .NET 应用程序,这样做对您很有帮助。
目标
学习在 Microsoft® .NET 中使用 COM+ 服务。
创建被服务的组件。
部署被服务的组件。
前提条件
要彻底理解本文内容,需要满足以下条件:
曾经使用过 Microsoft Transaction Server (MTS) 并在 Microsoft Visual Basic® 6.0 中分发过事务。
曾经使用过 COM+ 服务中的基于角色的安全性。
曾经在 COM+ 服务中创建和使用过队列。
非常熟悉 .NET 类。
能够在 .NET 中熟练创建控制台应用程序。
目录
在 .NET 中使用 COM+ 服务
开发基于事务的组件
基于角色的安全性
使用排队组件
自 Visual Basic 6.0 以来 COM+ 的变化
总结
在 .NET 中使用 COM+ 服务
您可能曾经使用 COM+ 应用程序来托管使用 Visual Basic 或 C++ 编写的组件。COM+ 提供了许多有价值的服务,例如事务处理、排队组件、实时激活、基于角色的安全性、共享属性等。使用 COM+ 托管组件的一个主要优点在于:不必编写任何代码,就可以更改组件的行为方式,例如将组件的事务支持设置为“需要”。通过在组件服务 MMC 管理单元中,在 COM+ 组件上设置单选按钮,每次创建组件时,都将在 COM+ 事务的上下文中创建相应的组件。当组件使用 COM+ 事务时,所有数据库事务都由分布式事务处理协调器 (DTC) 处理。图 1 显示了在组件服务界面中设置“需要”事务选项的一个示例。
500)this.width=500'>
图 1:需要事务的 COM+ 组件示例
设置组件安全性与设置事务支持一样简单。使用 COM+ 服务管理单元,您不用重新编译代码就可以决定哪个用户可以运行哪个组件,甚至哪个方法。
.NET 可以使用所有 COM+ 服务
在 .NET 框架中,只要您的类是从 System.EnterpriseServices.ServicedComponent 类派生的,就可以继续使用 COM+ 提供的所有服务。任何从 ServicedComponent 类派生的类都由 COM+ 服务托管,并且可以使用所有可用的 COM+ 服务。表 1 列出了 .NET 中支持的全部 COM+ 服务以及每个服务的简短说明。
表 1:可用的 COM+ 服务
COM+ 服务
说明
自动事务处理
应用声明事务处理功能
COM 事务处理集成器 (COMTI)
将 CICS 和 IMS 应用程序封装到自动化对象中
补偿资源管理器 (CRM)
对非事务性资源应用原子性和持久性属性
实时激活
通过方法调用激活对象,并在调用返回时停用此对象
松散耦合的事件
管理基于对象的事件
对象构造
在构造实例时向类实例传递持久字符串值
对象池
提供现成对象的池
排队组件
提供异步消息队列
基于角色的安全性
基于角色应用安全权限
共享属性
在服务器进程中的多个对象之间共享状态
同步(活动)
管理并发
XA 互操作性
支持 X/Open 事务处理模型
在 .NET 中使用 COM+ 服务的原因
如果要编写能够参与事务、利用基于角色的安全性或者与队列交互作用的 .NET 应用程序,就会用到 .NET 中提供的 COM+ 服务。正如您将在本文中了解到的,.NET 使这些服务很容易实现。
提示:如果 .NET 代码无需与 COM+ 服务一起工作,也就是说,您只在 .NET 框架中工作,那么请不要使用 System.EnterpriseServices,否则会造成性能下降。
COM+ 组件开发概述
在 .NET 中创建与 COM+ 服务交互的组件时,需要执行以下步骤。表 2 包含对各个步骤的说明。
创建类库。
创建所有类,使它们继承 System.EnterpriseServices.ServicedComponents 类。
创建程序集。
创建强名称。
表 2:创建 .NET 组件时使用的术语定义
术语
说明
类库
包含类的 .dll 项目类型,此类项目通常没有用户界面
System.EnterpriseServices.ServicedComponents
.NET 框架中的一个类,使用它才能与 COM+ 服务进行交互
程序集
对项目中所有类和接口的描述
强名称
从程序集生成 GUID,以便可以使用 COM+ 服务注册组件
开发基于事务的组件
在本文的第一部分,您将学习如何创建使用 COM+ 的事务性服务的 .NET 组件,还将学习如何编写组件以及与此组件交互的前端应用程序。
创建 COM+ 事务组件
要使 .NET 组件能够在 COM+ 服务下运行,需要执行以下步骤。首先,必须创建一个从 System.EnterpriseServices.ServicedComponent 类派生的类。这个基类提供了与 COM+ 服务交互所需的所有适当方法和属性。需要将该类标记为需要新事务,并将所创建的任何方法标记为在没有错误出现的情况下可以自动完成事务处理。下面是具体操作。
打开 Microsoft Visual Studio® .NET,创建一个新的 ClassLibrary 类型的项目。
将 Class1.vb 文件重命名为 COMPlusServices.vb。
打开 COMPlusServices.vb 文件,将类名 Class1 更改为 COMPlusServices。
在此新类中键入如下所示的代码:Imports System.EnterpriseServices
Imports System.Reflection
'********************************************
' COM+ 注册详细信息
' 提供 COM+ 应用程序名
<Assembly: ApplicationNameAttribute("ComPlusExample")>
' 提供具有强名称的程序集
<Assembly: _
AssemblyKeyFileAttribute("bin/ComPlusExample.snk")>
'********************************************
<TransactionAttribute(TransactionOption.Required)> _
Public Class COMPlusServices
Inherits ServicedComponent
Public Sub New()
MyBase.New()
End Sub
<AutoComplete()> Public Function DoTransaction() _
As String
Return "COM+ 成功"
End Function
End Class
此代码以导入多个名称空间开始,从而在声明组件时省略了一些键入内容。
接下来是 COM+ 注册详细信息。请输入以下代码行:' 提供 COM+ 应用程序名
<Assembly: ApplicationNameAttribute("ComPlusExample")>
此行指定 ApplicationNameAttribute 的值为 ComPlusExample。这是在 COM+ 目录中注册该 COM+ 应用程序时要使用的名称。第一次调用此组件后,当打开 MMC 管理单元的 COM+ 应用程序文件夹时,您会发现应用程序名称就是这个名称。
接下来的代码声明 AssemblyKeyFileAttribute 属性:<Assembly: _
AssemblyKeyFileAttribute("bin/ComPlusExample.snk")>
此属性通知 COM+ 目录有关强名称的信息所在的位置。在后面的步骤中,将创建用于描述 COM+ 组件的 .SNK 文件。
最后,使用以下代码声明类名 COMPlusServices:<TransactionAttribute(TransactionOption.Required)> _
Public Public Class COMPlusServices
此类名前面的属性通知 COM+,您要将事务属性设置为“需要”。添加此行代码相当于打开 COM+ 应用程序管理单元(如图 1 所示)并手动设置此属性。
该类中的下一行代码继承 System.EnterpriseServices 名称空间中的 ServicedComponent。Inherits ServicedComponent
如果不包含此行,将无法使此组件在 COM+ 下运行。
添加事务方法
现在,类已经设置完毕,可以创建真正能够实现某些功能的方法了。在您编写的代码中,DoTransaction 函数返回一个字符串值,但它只给出了您必须使用的语法,如果不使用此语法该方法将无法参与事务。<AutoComplete()> Public Function DoTransaction() As String
Return "COM+ 成功"
End Function
在此方法前面加上 <AutoComplete()> 属性很重要。这表示只要此方法中没有出现异常,当它结束时就会自动调用 SetComplete。如果该方法中存在异常,则 .NET 运行时将自动调用 SetAbort 方法。这与在 Visual Basic 6.0 中编写 COM 组件不同,在 Visual Basic 6.0 中,必须手动显式调用 SetComplete 和 SetAbort。
创建强名称
在编译组件之前,您需要为此组件的程序集指定一个强名称。如果不指定,COM+ 目录将不能识别该组件,也就无法注册它。实际上,您已经通过前面使用的 AssemblyKeyFile 属性指定了强名称,现在需要使用强名称工具 (Sn.exe) 创建强名称并使 GUID 与程序集关联。
打开命令提示。
要创建强名称,请在命令提示下键入以下代码,然后按 Enter 键。sn -k ComPlusExample.snk
将 ComPlusExample.snk 文件从硬盘驱动器的根目录(通常为 C:/)复制到项目所在文件夹的 bin 目录下。
现在,需要编译此程序,使它能生成在 COM+ 注册此组件必需的文件。在 Visual Studio .NET 中,在 Build(生成)菜单上,单击 Build(生成)。
生成客户端测试应用程序
现在,组件生成完毕,需要生成客户端应用程序来调用并测试此组件。创建简单的控制台应用程序,此程序中的模块文件的 Main 方法创建新组件实例,并调用 DoTransaction() 方法。以下是主要步骤:
在 Visual Basic .NET 中,创建新的控制台应用程序项目。
添加对刚创建的组件的引用。
键入如下所示的代码。Module modMain
Sub Main()
Dim objCOMPlus As New _
COMPlusJumpStart.COMPlusServices()
Console.WriteLine(objCOMPlus.DoTransaction)
Console.ReadLine()
End Sub
End Module
试一试
最后,运行此程序并查看其运行情况。
打开组件服务 MMC 管理单元,验证您的组件已经动态注册到 COM+ 目录中。您应该看到图 2 所示的界面。
编译并运行控制台应用程序。
500)this.width=500'>
图 2:COM+ 目录中的新建 .NET 服务组件
基于角色的安全性
如果多个用户调用在 COM+ 下运行的 COM 组件,您需要进行验证,只允许特定用户访问某个组件。COM+ 允许您定义角色并为其分配 NT 用户。定义并设置角色后,就可以指定哪些角色可以运行哪些组件,甚至指定可以运行组件上的哪些方法。
请在此 COMPlusServices 类中添加一个方法,以添加基于角色的安全性。您需要创建名为 Managers 的角色,并在新方法中进行测试,查看调用者是否为 Managers 角色。
添加基于角色的安全性的步骤
不用直接从组件服务 MMC 管理单元修改 COM+ 应用程序来添加安全角色,只需在项目中添加一个新属性。使用 SecurityRoleAttribute 类添加新的 Managers 角色。这个类的构造函数有两个参数:role(字符串值)和 everyone(布尔值)。role 参数指定要创建的角色的名称,everyone 参数指定是否将内置 Everyone 组添加到此角色的用户中。
在注释“COM+ 注册详细信息”下键入以下代码,将新的安全性角色添加到 COM+ 应用程序中。'********************************************
' COM+ 注册详细信息
' 基于角色的安全性属性
<Assembly: SecurityRoleAttribute("Managers", False)>
更改安全级别设置,以便在进程级和组件级执行访问检查。这使 COM+ 应用程序具有安全性调用上下文。
显示 COM+ 服务管理单元。
单击 Security(安全性)选项卡并更改安全级别,如图 3 所示。
500)this.width=500'>
图 3:在 COM+ 目录中设置安全级别属性
除了手动进行处理外,还可以在组件中添加属性,通知组件执行访问级别检查。以下是在 COMPlusServices 类一开始的“COM+ 注册详细信息”部分添加的代码。<Assembly: ApplicationAccessControlAttribute
(AccessChecksLevel:=AccessChecksLevelOption.ApplicationComponent)>
检查安全性角色
现在,将新方法添加到名为 IsManager 的类中。此方法将检查用户是否为具有 Managers 角色的成员。此方法是一个函数,它返回一个布尔值,表明调用者是否为 Managers 角色。要访问调用该方法的用户的安全上下文,需要使用 SecurityCallContext 类。通过调用 CurrrentCall 方法,获得当前用户的上下文。然后调用 IsCallerInRole 方法,并传递 Managers 作为此角色的名称。
将以下方法添加到 COMPlusServices 类中。Public Function IsManager() As Boolean
Dim objCallContext As SecurityCallContext = _
SecurityCallContext.CurrentCall
IsManager = _
objCallContext.IsCallerInRole("Managers")
End Function
现在,需要重新生成该组件以测试此新方法。
从 Visual Studio .NET 的 Build(生成)菜单中,单击 Rebuild Solution(重新生成解决方案)。
试一试
修改控制台客户端应用程序的 Sub Main() 方法中的代码。此代码应如下所示:Sub Main()
Dim objCOMPlus As New _
COMPlusJumpStart.COMPlusServices()
Console.WriteLine(objCOMPlus.DoTransaction)
Console.WriteLine(objCOMPlus.IsManager().ToString)
Console.ReadLine()
End Sub
在命令提示下键入您编译的可执行文件的名称,运行控制台应用程序。
第一次运行该代码时会发生异常,并说明访问被拒绝的原因是 Managers 角色中没有添加任何用户。要纠正这个异常,请将您自己添加为 Managers 中的用户,并再次运行该应用程序。这次应该不会出现任何异常。也可以在代码中添加异常处理。以下是添加了异常处理代码的客户端应用程序示例:Sub Main()
Try
Dim objCOMPlus As New _
COMPlusJumpStart.COMPlusServices()
Console.WriteLine(objCOMPlus.DoTransaction)
Console.WriteLine(objCOMPlus.IsManager().ToString)
Console.ReadLine()
Catch objException As Exception
Console.WriteLine("出现错误。 " _
& "详细信息: " _
& objException.Message)
Console.ReadLine()
End Try
End Sub
使用排队组件
在 COM+ 应用程序中,添加排队支持很简单。只需确保该应用程序作为服务器程序运行(进程外),然后在选项卡上设置 Queued(排队)和 Listen(侦听)属性。完成这些设置后,客户端应用程序就可以异步或同步调用组件。该功能的精妙之处在于,不必更改 COM 对象中的代码,只需在 COM+ 目录中更改其属性。
.NET 框架支持排队组件,而且,正如您期望的那样,您可以通过使用属性,而不用手动更改 COM+ 目录即可为组件提供排队支持。
请在 COMPlusServices 类中添加一个方法,然后在 .NET 客户端应用程序中使用 COM+ 排队组件服务异步调用它。
将 COM+ 应用程序作为服务器程序(进程外)。这是排队组件的要求。要使用属性达到此目的,请将以下代码添加到项目中:'********************************************
' COM+ 注册详细信息
<Assembly: ApplicationActivationAttribute(ActivationOption.Server)>
在组件中添加排队支持。使组件可访问 MSMQ 队列,并使其侦听自己的队列以处理消息。下面是使用属性完成此过程的代码:'********************************************
' COM+ 注册详细信息
<Assembly: ApplicationQueuingAttribute(Enabled:=True,
QueueListenerEnabled:=True)>
在类 QueueTest 中添加一个方法。确保它是子例程且不返回任何值。使用它在 Windows 应用程序日志中写入信息。此代码应如下所示:Public Sub QueueTest()
System.Diagnostics.EventLog.WriteEntry(_
"COMPlusServces", "队列测试", _
Diagnostics.EventLogEntryType.Error)
End Sub
就到这里吧。这就是为使组件成为 COM+ 排队组件需要完成的全部操作。
试一试
现在,应该通过创建另一个控制台应用程序并调用此组件,来尝试运行该排队组件。
创建新的控制台应用程序。
将以下代码添加到控制台应用程序的 Sub Main 过程中。Sub Main()
Dim objTest As COMPlusJumpStart.COMPlusServices
Dim strMoniker
strMoniker = _
"queue:/new:COMPlusJumpStart.COMPlusServices"
objTest = GetObject(strMoniker)
objTest.QueueTest()
End Sub
它将异步调用组件中的 QueueTest 方法。如果要同步调用此方法,可以象调用该组件中的所有其他方法一样调用它。
现在,可以运行此控制台应用程序,尝试运行此排队组件。
自 Visual Basic 6.0 以来 COM+ 的变化
您已经通过 Visual Basic 6.0 或 COM 了解了 .NET 中的许多内容。现在,您已经获得了在 .NET 框架中工作的好处,这有助于实现对象的平稳交互,您只需编写少量代码,执行少量维护即可。
这类简化操作中最典型的是,在 Visual Basic 6.0 中,必须手动显式调用 SetComplete 和 SetAbort。而在 .NET 中,SetComplete 和 SetAbort 由 <AutoComplete()> 属性调用。
Visual Basic .NET 和 Visual Basic 6.0 的另一个不同之处是,由于使用单线程单元线程模型,Visual Basic 6.0 组件不能使用 COM+ 对象池。而 Visual Basic .NET 组件是 .NET 组件,支持任何单元线程模型,所以可以使用 COM+ 对象池。
总结
可以看出,利用 .NET 框架可以方便地利用 COM+ 提供的服务。这意味着您可以将新的 .NET 组件添加到使用 COM 和 COM+ 编写的现有程序中,而且它们可以协同工作。这一点非常重要,因为这意味着您不必放弃现有的全部 COM 和 COM+ 代码。如果您从头开始生成新应用程序,强烈建议您完全在 .NET 框架中生成它,因为这样效率会更高。
关于作者
Tim McCarthy (MCSD, MCT) 是 InterKnowlogy 的总工程师,他利用最新的 Microsoft 技术设计并建立了多层应用程序。他经常在 DevDays 发表演讲,最近刚为 MSDN Field Content Team 编写了 .NET 培训内容。Tim 曾参与编写了许多由 Wrox 出版社出版的书,最近出版的一本书是《Professional VB.NET》。他还为《SQL Server Magazine》的“Developer DotNET Update”时事专栏撰写了多篇文章。
Paul D. Sheriff 是 PDSA, Inc. 的所有者。该公司位于南加利福尼亚州,是一家自定义软件开发和咨询公司。Paul 是南加利福尼亚的 MSDN 区域总监,著有《Paul Sheriff Teaches Visual Basic》一书,他为 Keystone Learning Systems 制作了 70 多套关于 Visual Basic、SQL Server、.NET 和 Web 开发的视频教材,最近还将与 Ken Getz 合作为 SAMS 写一本书,书名是《ASP.NET Jumpstart》。有关详细信息,请访问 PDSA, Inc. 的 Web 站点 www.pdsa.com。
关于 Informant Communications Group
Informant Communications Group, Inc. (www.informant.com) 是一家专注于信息技术行业的多媒体公司。ICG 成立于 1990 年,致力于与软件开发有关的出版物、会议、目录发布和 Web 站点等领域。ICG 在美国和英国均设有办事处,目前已成为享有盛誉的媒体和营销内容集成商,并以高质量的技术信息满足 IT 人员不断增长的需求。
© 2002 Informant Communications Group 和 Microsoft Corporation 版权所有。
技术编辑:PDSA, Inc.
|
阅读全文(10884) | 回复(9) | 编辑 | 精华 |
回复:在 .NET 中使用 COM+ 服务 |
小雨发表评论于2006/9/25 21:40:06 | 我也没有实践过 互相学习吧 可以qq联系的 在本网站上有
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
回复:在 .NET 中使用 COM+ 服务 |
里仁(游客)发表评论于2006/9/25 16:06:56 | 关于COM+我始终有一些问题没弄太明白,可以请教小雨吗?最好能留一个电话,呵呵。
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
delegate |
小雨发表评论于2006/8/19 10:44:07 |
一个delegate和一个接口之间的相似性,因为它们都将规范和执行分离开来。它们允许多个开发人员建立与规范相符合的执行。除此之外,方法标记必须被指定并且相互保持一致。
Delegate 是一种函数指针,但与普通的函数指针相比,区别主要有三:
1) 一个 delegate object 一次可以搭载多个方法(methods)[译注1],而不是一次一个。当我们唤起一个搭载了多个方法(methods)的 delegate,所有方法以其“被搭载到 delegate object 的顺序”被依次唤起——稍候我们就来看看如何这样做。
2) 一个 delegate object 所搭载的方法(methods)并不需要属于同一个类别。一个 delegate object 所搭载的所有方法(methods)必须具有相同的原型和形式。然而,这些方法(methods)可以即有 static 也有 non-static,可以由一个或多个不同类别的成员组成。
3) 一个 delegate type 的声明在本质上是创建了一个新的 subtype instance,该 subtype 派生自 .NET library framework 的 abstract base classes Delegate 或 MulticastDelegate,它们提供一组 public methods 用以询访 delegate object 或其搭载的方法(methods)
例1
using System;
namespace ConsoleApplication1{ /// <summary> /// Class1 的摘要说明。 /// </summary> class Class2 { public void func1(String ss) { System.Console.WriteLine("bad"+ss); } } class Class1 { public void func1(String ss) { System.Console.WriteLine("good"+ss); } } class Class3 { public delegate void MyDelegate(String name); /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] public static void Main(string[] args) { MyDelegate oo =new MyDelegate(new Class1().func1); oo("test"); MyDelegate oo2 =new MyDelegate(new Class2().func1); oo2("test"); System.Console.ReadLine(); } }}例2
using System;
namespace ConsoleApplication1{ /// <summary> /// Class1 的摘要说明。 /// </summary> class Class1 { public delegate void MyDelegate(String name); public static void func2(String ss) { System.Console.WriteLine("bad"+ss); } public static void func1(String ss) { System.Console.WriteLine("good"+ss); } /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] public static void Main(string[] args) { MyDelegate oo =new MyDelegate(Class1.func1); oo("test"); MyDelegate oo2 =new MyDelegate(Class1.func2); oo2("test"); System.Console.ReadLine(); } }}
例3
using System;
namespace ConsoleApplication1{ /// <summary> /// Class1 的摘要说明。 /// </summary> class Class2//执行者2 { public void func1(String ss) { System.Console.WriteLine("bad"+ss); } } class Class1//执行者1 { public void func1(String ss) { System.Console.WriteLine("good"+ss); } } class Class3//分配者 { public delegate void MyDelegate(String name); public void Execute(int i) { MyDelegate oo=null; switch(i) { case 0 : oo =new MyDelegate(new Class1().func1); break; case 1 : oo =new MyDelegate(new Class2().func1); break; } oo("test"); } } class Class4//领导下命令给分配着 { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] public static void Main(string[] args) { Class3 oo=new Class3(); oo.Execute(0); oo.Execute(1); System.Console.ReadLine(); } }}
goodtest
badtest
例4
using System;
namespace ConsoleApplication1{ /// <summary> /// Class1 的摘要说明。 /// </summary> class EvenExcute//事件执行者 { public void MyEventFunc(object sender, System.EventArgs e) { Console.WriteLine("My event is ok!"); } } class Class3//受 委托类 { public delegate void MyEventHandler(object sender, System.EventArgs e); private event MyEventHandler myevent; public Class3(System.EventArgs e) {
/*由于+= 和 -= 是唯一可以在声明了事件成员的类型外的事件上使用的操作,外部代码可以为一个事件添加或去掉句柄,但是不能通过任何其他途径获得或修改基本事件域或事件属性的数值。*/ myevent+=new MyEventHandler(new EvenExcute().MyEventFunc); myevent(this,e); } } class Class4//委托事件类 { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] public static void Main(string[] args) { EventArgs e = new EventArgs(); Class3 object1=new Class3(e); System.Console.ReadLine(); } }}
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
回复:在 .NET 中使用 COM+ 服务(个人翻译) |
小雨发表评论于2006/8/18 15:28:24 |
Loosely Coupled Events (LCE) 是 com+ 一个非常有用的特性。LCE可以允许com+组件初始化事件,这些事件最终由客户端引起。客户端应该通过com+ MMC 或者动态注册为com+的一个订阅者。发布者调用其中一个COM+事件组件方法并且发给所有的定约者。这种订约和发布者之间的联系只是接口 ,这种接口必须要被所有的有关系的部分实现。
LCE可以产生通知给组件或者应用而不用更细致的了解这些组件或者应用到底是怎么样的。你唯一要做的就是要这些组件或者应用实现这些接口 ,以便订购com+事件组件。而其他的事情则有com+自己去完成。
为了模拟LCE的强大,我们建立一个例子 :使得当一个数据库表格被web应用或者其他应用改变时,另一个web应用得到通知。当然这必须首先保证所有应用都可以访问数据库。这个任务可以通过建立一个com+服务应用达到。在这个com+服务礼貌完成select insert update 和delete方法。每一个应用里面应用里数据层类都应该使用这个com+服务提供的类当要提交sql指令的时候。。这个数据库管道类世界上就是发布者。每一个数据库指令最后都会调用以com+ 库或者事件类的服务的类。
首先。我们从事件类组建开始 我们先建立一个LCEventLibrary.Dll ,它是一个程序集包括一个接口和一个类,这个类就是作为com+库作为事件类。这个类里面使用了EventClass属性。注意这个类不可以作具体的事件,不可以被直接调用。这个类只是com+通知 订阅者的作用 如下图
极口和类的代码如下:public interface IMySink
{
void OnDBChange(string Action, string DBEntity);
}
[EventClass(FireInParallel = true)]
public class MyEventClass : ServicedComponent,IMySink
{
public void OnDBChange(string Action, string DBEntity)
{
throw(new
NotImplementedException("You should not call an event class directly! "));
}
}
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
回复:在 .NET 中使用 COM+ 服务 |
理解 COM+ 服务
除提供运行时环境外,COM+ 和 Windows 2000 也包含几个内置服务,这些服务对创建多层应用程序的程序员来说十分重要。有些多层应用程序也许仅需要利用一个或两个这种服务。其他多层应用程序也许需要使用所有这些服务。应该大致了解它们之间的相互关系,以便在最初设计阶段做出正确的决策。以下部分会简单概述分布式应用程序的最重要的平台服务。
Internet 信息服务
Internet 信息服务 (IIS) 是 Microsoft 的 Web 服务器。该产品最初为 Windows NT Server 创建。最新版本是 IIS 5.0,它是随 Windows 2000 发布的。像其他 Web 服务器产品一样,IIS 处理客户端应用程序发送的传入的 HTTP 请求。IIS 的早期版本主要被用于提供静态 Web 页。现在,很多基于 Web 的应用程序利用 IIS 在每个传入的请求之后运行自定义的处理。
IIS 向希望使用自定义服务器端逻辑创建 Web 应用程序的开发人员公开一个名为 Internet Server API (ISAPI) 的专有 API。使用 ISAPI 的程序员直接创建名为 ISAPI扩展和 ISAPI 过滤器??软件模块。尽管编写基于 ISAPI 的软件能够提供最高级别的性能和灵活性,但使用这种方法也需要付出代价:它需要使用 C 或者 C++ 进行开发,而不能使用 Visual Basic,并且要求程序员处理底层基础结构细节(如编写线程池管理器)。
很多公司不希望直接针对 ISAPI 编程,因为他们没有这方面的行家,或者不愿意投入必要的资金和时间。IIS 为 ISAPI 提供了框架作为替代解决方案,框架名为活动服务器页面 (ASP) 。ASP 框架本身就是一种 ISAPI 扩展,它允许程序员使用脚本语言和 Visual Basic 编写服务器端逻辑。
应该注意到,使用 ISAPI 或者 ASP 创建的 Web 应用程序可以提供纯粹的 HTML 解决方案(如果是你想要的)。您可以完全决定应用程序所支持的浏览器。您还可以创建纯粹的 HTML 解决方案来支持 Internet 风格的更广泛的用户群,或者在 Intranet 风格的环境中充分发掘一种浏览器的功能(如 Internet Explorer)。
很多公司已经创建了只使用 ASP 实现的高级站点。使用 Visual Basic、Scripting Edition (VBScript) 和 JavaScript 等脚本语言,以及诸如 Microsoft Visual InterDev 之类的开发工具,编写服务器端业务逻辑和数据访问代码变得相当容易。但是,公司也发现很难复用、维护和扩展遍布很多不同网页的业务逻辑。随着网站规模逐渐加大,这变得越发明显。更好的方法是在编译组件中封装业务逻辑和数据访问代码。
ASP 和 COM+ 之间的集成使得从 ASP 页面创建和运行自定义业务对象变得非常容易。这意味着可以使用组件来分发服务器逻辑,而不必使用 ASP 页面中嵌入的脚本。使用组件更易于复用、维护和扩展代码。这类组件可以使用 Visual Basic 创建,Visual Basic 提供了比任何基于 ASP 的开发工具更好的测试和调试工具。很多公司已经发现,综合使用 ASP 和 Visual Basic 可以在生产率、可维护性和性能之间提供更好的平衡。
Microsoft 消息队列服务
Microsoft 消息队列服务 (MSMQ) 是该平台另一个重要组成部分。MSMQ 是中间件服务,可以促进多层应用程序中各种进程之间的消息处理。如前所述,消息处理非常重要,因为它可以提供异步和无连接的通信,RPC 和 HTTP 都无法提供该功能。
MSMQ 是基于异步传递消息到命名队列的消息处理产品。在高级别,消息模型过程在客户端和服务器之间进行调用,除了任何一方可以在另外一方不在场情况下进行操作。两者之间的最大概念性差别是消息的行为是单向的,而 COM 方法调用既包含发送到对象的 RPC 请求,还包括返回到客户端的 RPC 响应。
借助于 MSMQ,客户端应用程序甚至可以在服务器应用程序脱机时发送请求消息。这也意味着服务器可以在所有客户端应用程序都脱机的情况下响应请求。在客户端应用程序和服务器可以由于各种原因无法建立连接的环境下,这种功能允许分布式应用程序作为一个整体继续运行。
那么何时需要使用 MSMQ 呢?让我们讨论一个典型的例子。在销售订单应用程序中,即使服务员应用程序没有运行,客户端仍可以向订单请求队列提交销售订单。然后,服务器应用程序会打开队列,开始处理订单请求。MSMQ 还能使服务器应用程序向发送方返回响应消息,好像它就是方法调用的响应一样。当涉及到消息处理时,只需要增加很少工作量。
MSMQ 也适合于拥有膝上型电脑用户的公司,这类计算机经常从网络中断开并重新建立连接。借助于 MSMQ,可以简单的创建客户端应用程序向网络上的队列发送消息。如果膝上型电脑脱机,MSMQ 会自动在临时的本地队列中存储消息。当膝上型电脑重新连接到网络时,MSMQ 会检测到网络可用,并自动把缓存的消息转发给适当的目的队列。如您所见,存储转发机制的本质原理都完全隐藏到底层平台中。
相对于基于 RPC 或者 HTTP 的产品,诸如 MSMQ 之类的消息处理产品也可以提供更好的交付保证。MSMQ 消息可以在事务范围内发送,以提供仅仅一次 的提交语义。这意味着 MSMQ 采取了很多额外的预防措施来确保消息能够最终到达目的地。当消息超时或者不能路由到目的地时,MSMQ 也提供额外的基础结构支持,能够将错误通知传回发送方。您可以得到保证:MSMQ 要么将消息传递到目的地,要么通知您消息传递不成功。MSMQ 消除了很多影响到基于 RPC 和 HTTP 的应用程序的丢失消息的问题。
队列组件
MSMQ 最初是在带有 Windows NT Option Pack 的 Windows NT 中提供的,发布时间是 1997 年 11 月。从那时起,Visual Basic 程序员就可以使用 MSMQ 来充分体验异步、无连接通信带来的好处了。但是,MSMQ 编程需要额外的代码,以便从客户端应用程序创建、准备和发送消息。它还要求编写服务器端侦听器应用程序。相比于与 COM 方法调用进行通信而言,使用 MSMQ 通信需要更多工作量才能发出请求并得到响应。
COM+ 提供一个名为队列组件 的服务,使您可以充分利用 MSMQ,而无须针对 MSMQ API 进行显示编程。队列组件服务就是构建在 MSMQ 之上的一个生产率层。创建队列组件的方式与创建标准 COM+ 组件的方式完全相同,只有一、两个限制。例如,不能设计带有输出参数或者返回值的方法。
一旦在 COM+ 应用程序中创建并安装了队列组件,就必须配置一个属性,说明所使用的接口应该进入队列。也必须配置 COM+ 应用程序进入队列,并且是侦听器。当完成如上任务后,队列组件服务会自动创建应用程序的特殊队列。也会设置一个系统提供的侦听服务,以便当传入消息到达时对其进行处理。
当队列组件在服务器上正确配置后,就可以编写使用它的客户端应用程序。客户端应用程序不会直接实例化队列组件的对象。相反,它会创建一个名为记录器的特殊客户端代理对象,只要客户端建立起连接,它看起来就像个真正的对象它看起来就像个真正的对象。然后客户端开始像往常一样开始方法调用。队列组件服务提供了一个基础结构,可以在 MSMQ 消息中记录这些方法调用,并把该数据通过网络传递到队列组件所安装的计算机上。队列组件服务的服务器端接收消息,创建队列组件的实例,并重放方法调用。
如您所见,队列组件的主要设计目标是提供 COM 方法的方便性,同时提供异步的无连接通信的优势。实际上,队列组件使用 MSMQ 作为底层传输协议,而不是 RPC。这样,队列组件就避免了很多与面向连接、同步协议相关的限制。
请注意,不必使用队列组件服务来利用 MSMQ。您完全可以直接对 MSMQ 进行编程。队列组件服务是面向生产率的框架,它隐藏了 MSMQ 编程中很多乏味的细节。像其他框架一样,它提供了更高的生产率,但是损失了灵活性。
MSMQ 可以完成的很多任务在队列组件中并不支持。只有当队列组件服务支持所需特性,并可以节省很多 MSMQ 编程时间时,才应该使用队列组件服务。它最有价值的特性之一是服务器端侦听器服务。只使用 Visual Basic 来创建多线程侦听器服务几乎是不可能的,所以如果想编写每秒钟处理许多消息的服务器端侦听器应用程序,并且不希望使用 C++ 进行开发的话,队列组件将是您的最佳选择。
COM+ 事件服务
有些多层应用程序要求特定用户或应用程序接收有趣事件的通知,如雇佣新职员、股票价格变化,或者降低重新进货的存货等级。<0} {0><I>COM+ Events </I>provide a service for sending and delivering event notifications between applications.<}0{>COM+ 事件提供在应用程序间发送和传递事件通知的服务。
在 COM+ 事件模型中,发送事件通知的应用程序被称作发布者。接收事件通知的应用程序被称作订阅者。COM+ 事件经常被称作松散耦合事件 (LCE) ??原因是发布者和订阅者都不了解对方。相反,一组事件在事件类 范围中被定义,并且这个事件类被安装在 COM+ 应用程序中。发布者和订阅者了解事件类,但是它们都不了解对方。
把发布者和订阅者分离开有很多好处。当创建发布者应用程序时,不必担心谁在侦听,这样就可以节省很多代码。并且在发布者应用程序投入运行后,当希望添加或者删除订阅者时不必修改发布者应用程序。而且,当您希望添加或者删除与事件类相关的发布者时,也不必修改订阅者。
以下简单概述了事件模型的工作机制。编写实现一个或者更多接口的事件类。每个接口定义一组方法,表示一组事件。编写订阅者组件来实现这些接口,并在它们被触发时响应事件。最后,编写发布者应用程序,从事件类创建对象,并当希望触发事件时调用各种方法。事件服务负责处理该方法,并把事件提交给每个订阅者。
订阅有两种类型:永久性订阅 和暂时订阅。当事件被提交到永久性订阅时,COM+ 事件服务会从配置的订阅者组件创建一个新对象,并调用与该事件相关的方法。如果订阅者应用程序没有运行,事件服务会唤醒它。应该注意到,对于永久性订阅而言,每当事件被触发时都会创建和部署一个对象。
第二种订阅类型是暂时订阅。当应用程序运行时,该应用程序会为自己注册一个指定的事件类,以在触发它们时侦听事件。在这种情况下,事件服务不会为每个事件创建和部署对象。两种订阅类型的主要区别是:暂时订阅者必须以编程方式创建一个新订阅,并注册一个回调函数以侦听事件。
相对于永久性订阅者而言,创建暂时订阅者需要更多代码。由于可以使用 COM+ 管理工具,创建永久性订阅者就非常容易了。同时,如果拥有事件类的服务器重新启动,永久性订阅者会继续工作,而不会出任何问题。但是,所有暂时订阅者必须创建并注册一个新订阅。
可扩展的事件通知体系结构需要异步通信。如果发布者必须等待每个订阅者处理其事件通知,系统也许会很繁忙。同时,有些应用程序也许需要以与 MSMQ 一致的无连接模式发送事件通知。COM+ 事件已紧密与队列组件集成,以提供异步和无连接通信的优势。发布者和订阅者都可以配置为使用队列组件,而不是 RPC。对于很多应用程序而言,只有当与队列组件服务一起使用时,COM+ 事件才有价值。
http://www.microsoft.com/china/MSDN/library/windev/COMponentdev/CDCOMplus4vb.mspx?mfr=true
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
回复:在 .NET 中使用 COM+ 服务 |
using System;using System.EnterpriseServices;using System.Reflection;[assembly: ApplicationName("EventClassLogger")][assembly: AssemblyDelaySign(false)][assembly: AssemblyKeyFile("EventClass.snk")]
namespace EventSystem{ /// <summary> /// Class1 的摘要说明。 /// </summary> public class Class1:ServicedComponent { public Class1() { // // TODO: 在此处添加构造函数逻辑 // } public string Write(string name) { return "COM+ 成功 from"+ name;
} }}
///client
using System;
namespace ConsoleApplication1{ /// <summary> /// Class1 的摘要说明。 /// </summary> class Class1 { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main(string[] args) { EventSystem.Class1 obj=new EventSystem.Class1(); System.Console.WriteLine(obj.Write("zj")); } }}
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
回复:在 .NET 中使用 COM+ 服务 |
事件类是由COM+事件服务提供的对象,它实现了事件接口,所以对于发布者来说,它扮演了订阅者的角色。当发布者要激发事件时,它创建一个事件类对象,调用相应的事件方法,然后释放对象的接口。COM+事件服务会决定如何通知订阅者,决定什么时候通知订阅者。如同队列组件情形一样,发布者和订阅者的生存时间可以被分离,从这个意义上讲,所有事件接口函数只能包含输入参数。
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
回复:在 .NET 中使用 COM+ 服务 |
COM+一方面提供了许多新的服务和一个一致的管理环境,另一方面它支持说明性编程模型(declarative programming model),也就是说,开发人员可以按尽可能通用的方式开发组件程序,把一些细节留到配置时刻再确定。举例来说,我们开发一个COM+组件,它支持负载平衡特性,但是我们在开发组件的时候,并不确定它是否使用负载平衡特性,而把是否支持负载平衡特性留待配置时刻再作决定。有的应用可能会需要负载平衡特性,而有的应用可能并不需要,我们可以通过COM+管理程序配置组件的属性来决定组件是否支持负载平衡特性。MTS安全模型实际上是一个典型的说明性编程技术,它把组件的安全角色信息留到配置时刻再给出确切的定义,而非编程时刻。COM+继承了MTS的安全模型。 利用COM+的服务和管理工具,以及随后发布的一些开发工具,开发一个COM+组件要比开发一个COM组件容易得多,因为COM+组件实际上是建立在COM+系统服务基础上的应用程序,我们可以避免底层繁琐的细节处理。通过COM+系统服务,我们在获得可靠性的同时,也使我们的组件或者应用程序更趋于标准化,在更广泛的范围内体现组件或者应用的多态性。
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
回复:在 .NET 中使用 COM+ 服务 |
COM和MTS把组件的所有配置信息都保存在Windows的系统注册表中,然而,COM+的做法有所不同,它把大多数的组件信息保存在一个新的数据库中,称为COM+目录(COM+ Catalog)。COM+目录把COM和MTS的注册模型统一起来,并提供了一个专门针对组件的管理环境。我们既可以通过COM+管理程序检查或设置COM+目录信息,也可以在程序中通过COM+提供的一组COM接口访问COM+目录信息。
|
个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除 |
» 1 »
|