经典技术文章翻译(1):COM+集成:.NET Enterprise Services 如何帮你建立分布式应用(2)

简介:
实现客户端
       当一个基于 CLR  组件服务类被编译和部署,你就需要在客户端调用它。长远来看,组件服务类没什么特别之处 ; 事实是使用 COM+  运行时服务是不相关的。  这个代码展示了简单类早期的定义 MyTxCfgClass:
using ESExample;
 
public class Client
{
 public static void Main(string[] args)
 {
    MyTxCfgClass tcc = new MyTxCfgClass();
     ... // use object as desired
 }
}
       当然,与所有的 CLR 代码,客户端必须引用组件服务类程序集。
csc /r:ESExample.dll Client.cs
细微的复杂性
       这里你会看到,服务类通过  .NET CLR 实现 COM+ 是相当的容易。  System.EnterpriseServices  命名空间里的类提供了可以使用 COM+ 运行时服务的 API 。运行时服务本身没什么改变;他们工作的方式还是  COM+ 开发者熟知的。已经说了,  集成 COM+ CLR  没有涉及到如此细微的复杂性。  有几个问题是使得使用 CLR 语言写  COM+  代码比我刚才提到的复杂的多。  有些问题会产生,因为 CLR 毕竟不是  COM   因为它可以做 COM 做不到的事情。这些问题是不能解决的 你只要知道如何 CLR 的特性如静态方法和垃圾回收器  如何影响 COM+  编程。
      
再学习这些问题前,你必须知道 CLR  的类和  and COM+  上下文环境的关系。  首先,调用继承自 ServicedComponent 的类的实例都会被 COM+  上下文环境边界侦听。这些对象称为上下文环境边界。调用没继承自 ServicedComponent 的类的实例就不会被上下文环境边界侦听。  这些对象称为 context-agile CLR 对象默认就是 context-agile   当你继承自 ServicedComponent 它们会变成 context-bound  ( 这个与  .NET remoting  上下文环境没有关系,我下面会讲到。  9 说明的这个架构
 9  上下文环境对象

     
非常有趣的是 CLR  对象可以实现类似 COM  对象和 COM+  上下文环境交互这样的行为。通过  COM ,调用对象通常默认都会被侦听 所有的对象都是 context-bound COM  对象是 context-agile  只有当它聚集了 freethreaded marshaler (FTM) 且不是第一个在 COM+  上下文环境里  被创建的对象 ( 因为它不是可识别的对象 )   这样情况下,调用不会被侦听。  新方法确保调用真的需要的时候被预处理和迟处理的好处是减少了侦听负荷。  特别地,如果组件服务类的实例返回了一个非组件服务类的实例  ( 例如一个  ADO.NET DataSet  对象 ) ,这个调用不会被侦听。  并且 DataSet 对象不需要做任何事情,它就是照常工作。
       第二个你应该知道的事情是,  除了减少真正需要的交叉上下文侦听外,  CLR/COM+ 集成尽可能地避免了托管类型和自有类型间的转换。  来自托管的 CLR  代码到 COM 的调用是比较昂贵的。重要的部分就是类型的前后转换 大部分在 CLR strings COM BSTRs 之间。  请求穿过 COM+ 环境边界需要  调用一些固有的代码,  组件已经相当聪明可以避免同样来自 CLR 且处在同一进程里的调用者和被调用者之间的类型转换。  或许有一天所有的 COM+  运行时服务都会用 CLR 语言重新实现,调转就不成问题了。  那时不管如何,这个优化都会使得 COM+  侦听更加快速。
静态方法和属性
       现在你知道了 CLR 代码如何关联上下文环境,  思考这个问题:如果一个基于 CLR  组件服务类  包括静态方法和属性访问器,  它将在什么上下文里执行呢?答案是调用者。  这个看起来不是很直观,  但是它确实很有意义当你想静态成员不是对象定义且不许要在对象驻留的上下文里访问。例如,组件服务类在  10 有个静态方法, 2   和静态属性, 4 。这个代码会在调用者的上下文里执行。  调用实例的方法 1   或者属性 3 ,通常在对象的上下文里执行。
     
这时你或许想知道当你在属性里保存了一个对象的静态引用且你想在另外一个上下问里引用会发生什么事情。基于 COM COM+ 编程里,  在被成为静态属性的全局变量里保存了一个原始的对象引用,  会导致严重的错误因为你不可以把对象不加包装地从原来的上下文里带走。使用基于 CLR COM+  代码,  这个就不是一个问题。  CLR  使用相当瘦的代理包装了每个组件服务类的实例子这样其它上下问的对象就不需要保留对象的直接引用。如果代码在一个保留基于 CLR  组件服务类引用在静态属性的的上下文执行。它实际保留的是一个引用。如果另一个上下文里的代码要通过静态属性访问它,  特定的代理就发现变化而且封装它自己保留的引用这样侦听就触发了。这个是有个优美的解决方案,本质上你可以任何地方保存基于 CLR 服务类的实例并且都会正确触发。
     
管理珍贵的资源
      我现在开始另外一个管理对象引用的话题 ' ,另外一个问题你必须注意 CLR 靠垃圾收集器回收内存。  这是个重要的事情因为它要自动帮助避免内存泄露并且释放闲置的内存。非常不幸的是,  垃圾收集器使得内存管理变的容易,但是他同样带来了其他问题,比如管理 COM+ 设计的对象变的困难。因此高效地管理资源是建立可伸缩的系统的关键,这正是 COM+  的设计目标,你需要知道如果合理地释放基于 CLR 的资源。
     
考虑  CLR 类使用到了 SqlConnection  对象连接数据库,  如下所示 :
public void UseADatabase(void)
{
 System.Data.SqlClient.SqlConnection =
      new System.Data.SqlClient.SqlConnection(…);
    …// use connection to execute statements
}
UseADatabase 方法的结束部分,  SqlConnection  对象被释放。  SqlConnection 对象封装了处理数据库的连接并且为了效率考虑被 ADO.NET 底层机制池化 (Beta 1  使用 COM+  对象池 ; Beta 2   使用了类似 COM+  对象池的机制 )   问题是  SqlConnection 对象管理的连接何时归还到对象池 不等垃圾收集器进入,就意识到 SqlConnection  对象不在被使用,就调用终结器。 finalizer  把连接归还给对象池,  然后 SqlConnection 对象的内存就被回收。
      
问题是数据库连接资源是非常珍贵的资源,你不能让他们无约束地飘荡在内存里,直到垃圾收集器来回收。  需要一些方法来回收这样的资源。一种方式就是强制垃圾收集器执行回收工作,如下所示 :
public void UseADatabase(void)
{
 System.Data.SqlClient.SqlConnection conn =
      new System.Data.SqlClient 。SqlConnection(…);
 … // use connection to execute statements
 conn = null;
 System.GC.Collect();   
}
然而,这个方法相当的笨拙且有很多潜在问题。
      更好的方法是调用 SqlConnection  对象实现的接口的  IDisposable.Dispose 方法。  IDisposable  接口在 System 命名空间,它规范拥有昂贵的要清理的资源的对象通过客户端定义操作释放资源代理垃圾收集器回收的行为。 SqlConnection 实现了 Dispose ,快速归还对象给对象池  ( 事实上和调用 finalizer 的作用一样 )
      
下面代码是新版本的 UseADatabase 方法,它显示的清除了 SqlConnection
public void UseADatabase(void)
{
 System.Data.SqlClient.SqlConnection conn =
      new System.Data.SqlClient.SqlConnection(…);
 try
 {
    … // use connection to execute statements
 }
 finally
 {
    Conn.Dispose();
 }
}
注意到 Dispose 出现在 finally 块里确保它可以执行,不管是否抛出异常。
      
那这个和 COM+ 与服务类有什么关系呢 首先,你的服务类很可能使用数据库连接和其它昂贵的资源,  所以如果你希望系统净化,你就应该知道如果合理地释放资源。  第二是,  所有基于 CLR  服务类  实现了 IDisposable.Dispose 方法,  因为基类, ServicedComponent 。你应该知道当客户端调用 Dispose 时发生了什么。默认实现的行为取决于你的组件服务类  使用了什么运行时服务。如果你没使用对象池激活,  Dispose 就会立即调用  finalizer ( 如果已经被垃圾收集器回收,就不会再调用 ) 。如果你的组件服务类  使用了对象池而不是 JIT  激活,  Dispose 调用 Deactivate 去通知对象已经离开它当前的上下文。然后它就调用  CanBePooled  去询问对象是否重用或销毁。  如果 CanBePooled 返回 true   对象会返回到对象池里。  返回 false   对象的 finalizer 就会调用  ( 如果已经被垃圾收集器回收,就不会再调用 )   非常重要是客户端为池化的对象调用方法 Dispose ,如下所示。
public void UseAPooledObject(void)
{
 MyPooledCfgClass pcc = new MyPooledCfgClass();
 try
 {
    …// use pooled object to do something
 }
 finally
 {
    Pcc.Dispose();
 }
}
       如果不调用 Dispose ,对象  ( 如描述的数据库连接 )   只有等到垃圾收集器回收资源。  最后,  如果你自己实现组件服务类的 Dispose 方法,  你必须调用基类的实现去实现这些描述的行为。
[ Synchronization(SynchronizedOption.Required) ]
public class MyCfgClass : ServicedComponent
{
 public new void Dispose()
 {
    … // do whatever
    Base.Dispose(); // call base to clean up
 }
}
     你或许想知道  JIT  激活和反激活一个对象在方法的结束。  那解决了资源的管理问题了吗 ? 答案是否。  反激活使得对象在结束调用前释放自己成员所有的资源,  同样包括想使用相同资源的的每个方法调用。你可以通过不保存任何资源的方式达到这个目的。如果你没有选择  JIT  激活  和反激活在每次方法调用的结尾,  知道客户端调用 Dispose 实际上是强制你的对象重激活到饭激活并且重新终结一次。通常情况下,  CLR 的转换不会改变的 JIT  激活规则。  应该避免使用它除非运行时服务需要它  ( 比如声明的服务 因为它不会更高效,    比你自己管理昂贵的资源效率低。
展望
      ServicedComponent  类继承自  System ContextBoundObject   它又继承自 System MarshalByRefObject   这个基类可以使对象可以通过 .NET remoting 机制  被访问到。在 Remoting 顶层  上进行 CLR/COM+ 集成有两个好处。首先你能通过 Remoting 层使用 SOAP 访问 COM+  运行时服务的远程对象。但是你不能够使用 SOAP 传递事务到另外的进程  ( 非你所愿,  但道理如此 )   第二点,打开了新版的新的基于 CLR Remoting 上下文架构实现的 COM+  运行时服务的方式  这是现在的 COM+ 所没有用到的。  将来一定会够发生。  真要这样,服务就可以与 SOAP 或者其他的传输无逢集成,并且上下文就可以真的可以扩展了。那时,  已经正确跨出一大步的 CLR  就会使得 COM+ 编程变的更加容易。
 
相关文章 :
Windows XP: Make Your Components More Robust with COM+ 1.5 Innovations
House of COM: Migrating Native Code to the.NET CLR
the "samples"technologies"component 服务  subdirectory of the.NET Framework SDK
事务 al COM+: Building  可伸缩的应用系统  by Tim Ewald (Addison-Wesley, 2001)
作者 Tim Ewald : DevelopMento 的首席科学家,   最近出版的   事务性 COM+:  创建可伸缩的应用系统  (Addison-Wesley  2001) 的作者
翻译 Frank Xu Lei : 程序员,技术博客 http://www.cnblogs.com/frank_xl/
来自 10  2001  MSDN 杂志



 本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/321005,如需转载请自行联系原作者


相关文章
|
29天前
|
机器学习/深度学习 Python
堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能
本文深入探讨了堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能。文章详细介绍了堆叠的实现步骤,包括数据准备、基础模型训练、新训练集构建及元学习器训练,并讨论了其优缺点。
50 3
|
1月前
|
前端开发 JavaScript 测试技术
前端测试技术中,如何提高集成测试的效率?
前端测试技术中,如何提高集成测试的效率?
|
24天前
|
机器学习/深度学习 人工智能 自然语言处理
Voice-Pro:开源AI音频处理工具,集成转录、翻译、TTS等一站式服务
Voice-Pro是一款开源的多功能音频处理工具,集成了语音转文字、文本转语音、实时翻译、YouTube视频下载和人声分离等多种功能。它支持超过100种语言,适用于教育、娱乐和商业等多个领域,为用户提供一站式的音频处理解决方案,极大地提高工作效率和音频处理的便捷性。
97 10
Voice-Pro:开源AI音频处理工具,集成转录、翻译、TTS等一站式服务
|
3天前
|
存储 缓存 负载均衡
从零到一:分布式缓存技术初探
分布式缓存通过将数据存储在多个节点上,利用负载均衡算法提高访问速度、降低数据库负载并增强系统可用性。常见产品有Redis、Memcached等。其优势包括性能扩展、高可用性、负载均衡和容错性,适用于页面缓存、应用对象缓存、状态缓存、并行处理、事件处理及极限事务处理等多种场景。
16 1
|
7天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
34 2
|
20天前
|
机器学习/深度学习 自然语言处理 监控
智能客服系统集成技术解析和价值点梳理
在 2024 年的智能客服系统领域,合力亿捷等服务商凭借其卓越的技术实力引领潮流,它们均积极应用最新的大模型技术,推动智能客服的进步。
55 7
|
1月前
|
jenkins 测试技术 持续交付
探索自动化测试在持续集成中的应用与挑战
本文深入探讨了自动化测试在现代软件开发流程,特别是持续集成(CI)环境中的关键作用。通过分析自动化测试的优势、实施策略以及面临的主要挑战,旨在为开发团队提供实用的指导和建议。文章不仅概述了自动化测试的基本原理和最佳实践,还详细讨论了如何克服实施过程中遇到的技术难题和管理障碍,以实现更高效、更可靠的软件交付。
|
28天前
|
消息中间件 Java Kafka
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
43 1
|
1月前
|
传感器 前端开发 Android开发
在 Flutter 开发中,插件开发与集成至关重要,它能扩展应用功能,满足复杂业务需求
在 Flutter 开发中,插件开发与集成至关重要,它能扩展应用功能,满足复杂业务需求。本文深入探讨了插件开发的基本概念、流程、集成方法、常见类型及开发实例,如相机插件的开发步骤,同时强调了版本兼容性、性能优化等注意事项,并展望了插件开发的未来趋势。
42 2

热门文章

最新文章