WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成

原文:WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成

在这之前,我写过深入介绍MS EnterLib PIAB的文章(参阅《MS Enterprise Library Policy Injection Application Block 深入解析[总结篇]》),也写过WCF与PIAB的集成(参阅:《WCF后续之旅(8):通过WCF Extension 实现与MS Enterprise Library Policy Injection Application Block 的集成》)、WCF与Unity的集成(参阅《WCF后续之旅(7):通过WCF Extension实现和Enterprise Library Unity Container的集成》)以及Unity与PIAB的集成(参阅《Enterprise Library深入解析与灵活应用(1):通过Unity Extension实现和Policy Injection Application Block的集成》、《Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成》)。由于部分实现时基于EnterLib、Unity前一个版本,在新的版本中(EnterLib V4.1与Unity 1.2)中,MS通过Unity对PIAB进行了重新设计与实现,所以我们很有必要重拾着这个话题,谈谈对于新的EnterLib和Unity,如何将PIAB和Unity集成到WCF之中。(Source Code从这里下载)

一、设计原理简述

在EnterLib中,PIAB与Unity的定位分别是轻量级的IoC Container(或者DI Container)与AOP框架。PIAB采用Method Call Interception的机制实现了策略的动态注入,其本身依赖于Interceptable对象的创建;UnityContainer建立在ObjectBuilder2之上,本质上是一个用于对象创建的容器。所以,我们可以通过UnityContainer按照PIAB的要求创建Interceptable对象,就能实现Unity与PIAB之间的集成(参阅《Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成》)。

Unity与WCF之间的集成,本质上就是让WCF使用UnityContainer进行服务实例的创建。而WCF框架内部,服务实例的创建同时一个特殊的对象——InstanceProvider。所以我们可以通过自定义InstanceProvider,并借助UnityContainer进行服务实例的提供,那么就能实现Unity与WCF两者之间的集成。所以,创建基于UnityContainer的InstanceProvider是关键。

二、创建基于UnityContainer的InstanceProvider:UnityInstanceProvider

在WCF框架内部,InstanceProvider用户进行服务实例的提供。所有的InstanceProvider实现了接口System.ServiceModel.Dispatcher.IInstanceProvider,下面是IInstanceProvider的定义。服务实例提供实现在GetInstance中,而ReleaseInstance用于实现对服务实例的释放和资源回收。

1: public interface IInstanceProvider
2: {

4:     object GetInstance(InstanceContext instanceContext);

5:     object GetInstance(InstanceContext instanceContext, Message message);

6:     void ReleaseInstance(InstanceContext instanceContext, object instance);

7: }

我们现在的目的就是创建一个基于Unity的InstanceProvider,借助UnityContainer提供对GetInstance方法的实现,我姑且把这个自定义的InstanceProvider称为UnityInstanceProvider。在正式介绍UnityInstanceProvider的具体实现之前,我先介绍一个辅助类型的定义:UnityTypeMapping。

我们知道,UnityContainer采用动态注册接口或者抽象类于具体类型的匹配关系,使得我们可以利用UnityContaner实现基于接口或者抽象类的方式创建我们希望的具体类的对象。UnityTypeMapping用以描述类型的匹配,其定义如下。Type和Mapto分别表示相应的类型(接口或者抽象类)与被匹配的类型(具体类),Name则表示该Mapping Entry的名称(唯一标识)。

1: public class UnityTypeMapping
2: {

3:     public Type Type

4:     { get; set; }

5: 

6:     public Type MapTo

7:     { get; set; }

8: 

9:     public string Name

0:     { get; set; }

1: }

Unity可以采用编程和配置的方式实现类型的匹配,在真正的系统开发中,后者是首选。为了实现类型匹配配置(UnityTypeElementCollection)到我们定义的UnityTypeMapping列表(IList<UnityTypeMapping>)之间的转化,我定义了下面一个扩展方法(Extension Method):Copy。

1: public static class Extension
2: {

3:     public static IList<UnityTypeMapping> Copy(this UnityTypeElementCollection unityTypeElements)

4:     {

5:         IList<UnityTypeMapping> mappings = new List<UnityTypeMapping>();

6:         foreach (UnityTypeElement type in unityTypeElements)

7:         {

8:             mappings.Add(new UnityTypeMapping { Type = type.Type, MapTo = type.MapTo, Name = type.Name });

9:         }

0: 

1:         return mappings;

2:     }

3: }

下面列出了UnityInstanceProvider的具体定义。属性ContractType与Container分别代表服务契约与用于创建服务实例的UnityContainer对象,字段_registeredTypeMapping表示当前UnityContainer相关的类型匹配集合。出于性能的考虑,为了避免UnityContainer的频繁创建和类型匹配关系的频繁解析,我通过两个静态属性|字段来保存它们(Containers和registeredTypeMappings,Key为Container的名称)。在构造函数中接受两个输入参数:contractType与containerName,分别表示服务契约类型与相应UnityContainer的名称。根据containerName判断相应的UnityContainer是否已经创建,如果是,则直接从上述的两个静态变量中提取相应的UnityContainer和类型匹配列表。否则,重新创建UnityContainer,加载相应的配置信息对其进行配置。需要特别指出的是,在对创建的UnityContainer进行初始化的时候,添加了一个特殊的UnityContainerExtension:ExtendedIntercepiton,该UnityContainerExtension用户实现Unity与PIAB的集成,在《Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成》中对ExtendedIntercepiton的实现原理具有详细的介绍。

在GetInstance方法中,我们通过UnityContainer根据服务契约(接口)类新进行具体服务实例的创建。在创建之前,我们需要判断服务契约类型与服务类型之间的类型匹配是否已经注册到UnityContainer中,如果没有,则进行注册,并将类型匹配添加到当前类型匹配列表(_registeredTypeMappings)和全局类型匹配列表(registeredTypeMappings)中。

1: public class UnityInstanceProvider : IInstanceProvider
  2: {

  3:     private static object syncHelper = new object();

  4:     private static IDictionary<string, IList<UnityTypeMapping>> registeredTypeMappings;

  5:     public static IDictionary<string, IUnityContainer> Containers

  6:     { get; private set; }

  7: 

  8:     private IList<UnityTypeMapping> _registeredTypeMappings;

  9:     public Type ContractType

 10:     { get; private set; }

 11:     public IUnityContainer Container

 12:     { get; private set; }

 13: 

 14:     static UnityInstanceProvider()

 15:     {

 16:         registeredTypeMappings = new Dictionary<string, IList<UnityTypeMapping>>();

 17:         Containers = new Dictionary<string, IUnityContainer>();

 18:     }

 19: 

 20:     public UnityInstanceProvider(Type contractType, string containerName)

 21:     {

 22:         if (contractType == null)

 23:         {

 24:             throw new ArgumentNullException("contractType");

 25:         }

 26: 

 27:         this.ContractType = contractType;

 28: 

 29:         string key = containerName ?? string.Empty;

 30:         if (Containers.ContainsKey(key))

 31:         {

 32:             this.Container = Containers[key];

 33:             this._registeredTypeMappings = registeredTypeMappings[key];

 34:             return;

 35:         }

 36: 

 37:         UnityContainerElement containerElement = this.GetUnitySettings(containerName);

 38:         IUnityContainer container = new UnityContainer();

 39:         if (null != containerElement)

 40:         {

 41:             containerElement.Configure(container);

 42:         }

 43:         container.AddNewExtension<ExtendedInterception>();

 44:         PolicyInjectionSettings section = (PolicyInjectionSettings)ConfigurationSourceFactory.Create().GetSection("policyInjection");

 45:         if (section != null)

 46:         {

 47:             section.ConfigureContainer(this.Container, ConfigurationSourceFactory.Create());

 48:         }

 49:         lock (syncHelper)

 50:         {

 51:             if (!Containers.ContainsKey(key))

 52:             {

 53:                 Containers[key] = container;

 54:                 registeredTypeMappings[key] = containerElement.Types.Copy();

 55:             }

 56:         }

 57: 

 58:         this.Container = container;

 59:         this._registeredTypeMappings = registeredTypeMappings[key];

 60:     }

 61: 

 62:     #region IInstanceProvider Members

 63: 

 64:     public object GetInstance(InstanceContext instanceContext, Message message)

 65:     {

 66:         string contractServiceTypeMappingName = string.Empty;

 67:         var contractServiceTypeMappings = from mapping in this._registeredTypeMappings

 68:                                           where mapping.Type == this.ContractType &&

 69:                                           mapping.MapTo == instanceContext.Host.Description.ServiceType

 70:                                           select mapping;

 71:         if (contractServiceTypeMappings.Count() == 0)

 72:         {

 73:             contractServiceTypeMappingName = Guid.NewGuid().ToString();

 74:             this.Container.RegisterType(this.ContractType, instanceContext.Host.Description.ServiceType, contractServiceTypeMappingName);

 75:             this._registeredTypeMappings.Add(new UnityTypeMapping { Type = this.ContractType, MapTo = instanceContext.Host.Description.ServiceType, Name = contractServiceTypeMappingName });

 76:         }

 77:         else

 78:         {

 79:             contractServiceTypeMappingName = contractServiceTypeMappings.ToArray<UnityTypeMapping>()[0].Name;

 80:         }

 81: 

 82:         return this.Container.Resolve(this.ContractType, contractServiceTypeMappingName);

 83:     }

 84: 

 85:     private UnityContainerElement GetUnitySettings(string containerName)

 86:     {

 87:         UnityConfigurationSection unitySection = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;

 88:         if (unitySection == null)

 89:         {

 90:             return null;

 91:         }

 92: 

 93:         if (string.IsNullOrEmpty(containerName))

 94:         {

 95:             return unitySection.Containers.Default;

 96:         }

 97:         else

 98:         {

 99:             return unitySection.Containers[containerName];

100:         }

101:     }

102: 

103:     public object GetInstance(InstanceContext instanceContext)

104:     {

105:         return this.GetInstance(instanceContext, null);

106:     }

107: 

108:     public void ReleaseInstance(InstanceContext instanceContext, object instance)

109:     {

110:         IDisposable disposable = instance as IDisposable;

111:         if (disposable != null)

112:         {

113:             disposable.Dispose();

114:         }

115:     }

116: 

117:     #endregion

118: }

三、为UnityInstanceProvider创建Behavor对象

自定义行为(Behavior)是进行WCF扩张最为典型和常用的方式。按照作用域的不同,WCF的行为可以分为以下四类:契约行为(Contract Behavior)、服务行为(Service Contract)、终结点行为(Endpoint Behavior)和操作行为(Operation Behavior)。为了将上面自定义的UnityInstanceProvider应用到WCF服务端的分发系统,定义了如下一个行为类型:UnityIntegrationBehaviorAttribute。我们可以看出,UnityIntegrationBehaviorAttribute同时实现了IServiceBehavior、IContractBehavior和IEndpointBehavior,所以既是一个服务行为,也是一个契约行为,同时还是一个终结点行为。同时UnityIntegrationBehaviorAttribute继承了Attribbute,所以同时可以以Attribute的形式应用到服务契约(作为契约行为)类型和服务(作为服务类型)。你同样可以通过配置的方式以服务行为和终结点行为的方式应用该UnityIntegrationBehaviorAttribute。如果想采用配置的方式,你还需要定义相关的BehaviorExtensionElement,由于篇幅的问题,我就不就对BehaviorExtensionElement的问题作介绍了。

1: using System;
 using System.Linq;

 using System.ServiceModel;

 using System.ServiceModel.Channels;

 using System.ServiceModel.Description;

 using System.ServiceModel.Dispatcher;

 namespace Artech.UnityIntegration

 {

     public class UnityIntegrationBehaviorAttribute : Attribute, IServiceBehavior, IContractBehavior,IEndpointBehavior

     {

         public string ContainerName

         { get; set; }

 

         #region IEndpointBehavior Members

 

         public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)

         {            

         }

 

         public void ApplyClientBehavior(ServiceEndpoint endpoint,ClientRuntime clientRuntime)

         {           

         }

 

         public void ApplyDispatchBehavior(ServiceEndpoint endpoint,EndpointDispatcher endpointDispatcher)

         {

             endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(endpoint.Contract.ContractType, this.ContainerName);

         }

 

         public void Validate(ServiceEndpoint endpoint)

         {            

         }

 

         #endregion

 

         #region IContractBehavior Members

 

         public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)

         {

         }

 

         public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint,ClientRuntime clientRuntime)

         {

         }

 

         public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint,DispatchRuntime dispatchRuntime)

         {

             dispatchRuntime.InstanceProvider = new UnityInstanceProvider(endpoint.Contract.ContractType, this.ContainerName);

         }

 

         public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)

         {

         }

 

         #endregion

 

         #region IServiceBehavior Members

 

         public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)

         {

         }

 

         public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)

         {

             foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)

             {

                 foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)

                 {

                     endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(GetContractType(serviceHostBase, endpointDispatcher), this.ContainerName);

                 }

             }

         }

 

         private Type GetContractType(ServiceHostBase serviceHostBase, EndpointDispatcher endpointDispatcher)

         {

             var endpoint = serviceHostBase.Description.Endpoints.Where(item => item.Contract.Name == endpointDispatcher.ContractName &&

                 item.Contract.Namespace == endpointDispatcher.ContractNamespace).ToArray<ServiceEndpoint>()[0];

             return endpoint.Contract.ContractType;

 

         }

         public void Validate(ServiceDescription serviceDescription,ServiceHostBase serviceHostBase)

         {

         }

 

         #endregion

     }

 }

四、将UnityIntegrationBehavior应用到WCF应用中

为了演示UnityIntegrationBehavior的效果,我们创建了一个简单的WCF实例应用。我们采用《Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成》中同步时间提供的例子,通过一个服务得到同步的当前时间。下面是服务契约的定义:

1: using System;
2: using System.ServiceModel;

3: namespace Artech.UnityIntegrationDemo.Contracts

4: {

5:     [ServiceContract(Namespace="urn:artech.com")]

6:     public interface ISyncTimeProvision

7:     {

8:         [OperationContract]

9:         DateTime GetCurrentTime();

0:     }

1: }

 

实现了该服务契约的SyncTimeProvisionService本是并不具体实现不同时间的提供,而是通过另一个组件SyncTimeProvider。你可以将SyncTimeProvider看成是同一个应用的另一个模块,将此例子看成是一个典型的跨模块调用。为了实现真正的模块化,达到模块之间的松耦合,我们借助Unity,采用“属性注入(Propetry Setter Injection)”的方式,通过接口的方式(ISyncTimeProvider)调用另一个模块。为了证实PIAB的效果,我在SyncTimeProvider上面应用了CachingCallHandlerAttribute,如果该CallHandler生效的话,方法返回的结果将会被缓存,在缓存过期之前,你将得到相同的时间。而我们定义的UnityIntegrationBehaviorAttribute以服务行为的方式直接应用到服务类型(SyncTimeProvisionService)上。

 
 1: using System;

 2: using Artech.UnityIntegration;

 3: using Artech.UnityIntegrationDemo.Contracts;

 4: using Microsoft.Practices.Unity;

 5: 

 6: namespace Artech.UnityIntegrationDemo.Services

 7: {

 8:     [UnityIntegrationBehavior(ContainerName="myContainer")]

 9:     public class SyncTimeProvisionService : ISyncTimeProvision

10:     {

12:         [Dependency]

13:         public ISyncTimeProvider SyncTimeProvider

14:         { get; set; }

15: 

16:         #region ISyncTimeProvision Members

17: 

18:         public DateTime GetCurrentTime()

19:         {

20:             return this.SyncTimeProvider.GetCurrentTime();

21:         }

22: 

23:         #endregion

24:     }

25: 

26:     public interface ISyncTimeProvider

27:     {

28:         DateTime GetCurrentTime();

29:     }

30: 

31:     [CachingCallHandler]

32:     public class SyncTimeProvider : ISyncTimeProvider

33:     {

34:         #region ISyncTimeProvider Members

35: 

36:         public DateTime GetCurrentTime()

37:         {

38:             return DateTime.Now;

39:         }

40: 

41:         #endregion

42:     }

43: }

在服务寄宿的配置中,提供了WCF服务和Unity的相关设置:

 
 1: <?xml version="1.0" encoding="utf-8" ?>

 2: <configuration>

 3:   <configSections>

 4:     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

 5:   </configSections>

 6:     <system.serviceModel>

 7:         <services>

 8:             <service name="Artech.UnityIntegrationDemo.Services.SyncTimeProvisionService">

 9:                 <endpoint address="http://127.0.0.1:3721/synctimeprovisionservice"

10:                     binding="ws2007HttpBinding" bindingConfiguration="" contract="Artech.UnityIntegrationDemo.Contracts.ISyncTimeProvision" />

11:             </service>

12:         </services>

13:     </system.serviceModel>

14:   <unity>

15:     <typeAliases>

16:       <typeAlias alias="ISyncTimeProvider" type="Artech.UnityIntegrationDemo.Services.ISyncTimeProvider, Artech.UnityIntegrationDemo.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

17:       <typeAlias alias="SyncTimeProvider" type="Artech.UnityIntegrationDemo.Services.SyncTimeProvider, Artech.UnityIntegrationDemo.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

18:     </typeAliases>

19:     <containers>

20:       <container name="myContainer">

21:         <types>

22:           <type type="ISyncTimeProvider" mapTo="SyncTimeProvider" />

23:         </types>

24:       </container>

25:     </containers>

26:   </unity>

27: </configuration>

 

当服务成功寄宿,在Console Appliation下,执行下面一段服务端调用程序,你将得到下面的输出。从输出结果中,我们可以清晰地看到,返回的5个返回的时间均是相同的,由此我们可以看出应用才SyncTimeProvider上面的CachingCallHandlerAttribute生效了。进而证明了PIAB和Unity、Unity和WCF的有效集成:

 
 1: using System;

 2: using System.ServiceModel;

 3: using System.Threading;

 4: using Artech.UnityIntegrationDemo.Contracts;

 5: 

 6: namespace Artech.UnityIntegrationDemo.Client

 7: {

 8:     class Program

 9:     {

10:         static void Main(string[] args)

11:         {

12:             using (ChannelFactory<ISyncTimeProvision> channelFactory = new ChannelFactory<ISyncTimeProvision>("synctimeprovisionservice"))

13:             {

14:                 ISyncTimeProvision proxy = channelFactory.CreateChannel();

15:                 using (proxy as IDisposable)

16:                 {

17:                     try

18:                     {

19:                         for (int i = 0; i < 5; i++)

20:                         {

21:                             Console.WriteLine("The current time is {0}", proxy.GetCurrentTime());

22:                             Thread.Sleep(1000);

23:                         }

24:                     }

25:                     catch (CommunicationException)

26:                     {

27:                         (proxy as ICommunicationObject).Abort();

28:                         throw;

29:                     }

30:                     catch (TimeoutException)

31:                     {

32:                         (proxy as ICommunicationObject).Abort();

33:                         throw;

34:                     }

35:                 }

36:             }

37: 

38:             Console.Read();

39:         }

40:     }

41: }

42: 

 

时间: 2024-08-28 12:26:46

WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成的相关文章

《WCF技术剖析》博文系列汇总[持续更新中]

http://www.cnblogs.com/artech/archive/2009/11/21/1607686.html 近半年以来,一直忙于我的第一本WCF专著<WCF技术剖析(卷1)>的写作,一直无暇管理自己的Blog.在<WCF技术剖析(卷1)>写作期间,对WCF又有了新的感悟,为此以书名开始本人的第三个WCF系列.本系列的目的在于对<WCF技术剖析>的补充,会对书中的一些内容进行展开讲述,同时会囊括很多由于篇幅的原因忍痛割弃的内容. [第1篇] 通过一个ASP

WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化

在本篇文章中,我们将讨论WCF四大契约(服务契约.数据契约.消息契约和错误契约)之一的消息契约(Message Contract).服务契约关注于对服务操作的描述,数据契约关注于对于数据结构和格式的描述,而消息契约关注的是类型成员与消息元素的匹配关系. 我们知道只有可序列化的对象才能通过服务调用在客户端和服务端之间进行传递.到目前为止,我们知道的可序列化类型有两种:一种是应用了System.SerializableAttribute特性或者实现了System.Runtime.Serializat

WCF技术剖析之三十:一个很有用的WCF调用编程技巧[下篇]

原文:WCF技术剖析之三十:一个很有用的WCF调用编程技巧[下篇] 在<上篇>中,我通过使用Delegate的方式解决了服务调用过程中的异常处理以及对服务代理的关闭.对于<WCF技术剖析(卷1)>的读者,应该会知道在第7章中我通过类似于AOP的方式解决了相似的问题,现在我们来讨论这个解决方案. 通过<服务代理不能得到及时关闭会有什么后果?>的介绍,我们知道了及时关闭服务代理的重要意义,并且给出了正确的编程方式.如果严格按照上面的编程方式,就意味着对于每一个服务调用,都要

WCF技术剖析之三十:一个很有用的WCF调用编程技巧[上篇]

原文:WCF技术剖析之三十:一个很有用的WCF调用编程技巧[上篇] 在进行基于会话信道的WCF服务调用中,由于受到并发信道数量的限制,我们需要及时的关闭信道:当遇到某些异常,我们需要强行中止(Abort)信道,相关的原理,可以参考我的文章<服务代理不能得到及时关闭会有什么后果?>.在真正的企业级开发中,正如我们一般不会让开发人员手工控制数据库连接的开启和关闭一样,我们一般也不会让开发人员手工去创建.开启.中止和关闭信道,这些工作是框架应该完成的操作.这篇文章,我们就来介绍如果通过一些编程技巧,

WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构

原文:WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构 细算起来,已经有好几个月没有真正的写过文章了.近半年以来,一直忙于我的第一本WCF专著<WCF技术剖析>的写作,一直无暇管理自己的Blog.到目前为止<WCF技术剖析(卷1)>的写作暂告一段落,初步预计于下个月由武汉博文视点出版.在<WCF技术剖析>写作期间,对WCF又有了新的感悟,为此以书名开始本人的第三个WCF系列.本系列的目的在于对<WCF技术剖析>的补充,会对书中的一些内容进行展

WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置:通过ChannelFactory<TChannel>创建服务代理对象.在这篇文章中,我们采用一种独特的方式进行服务的调用.从本质上讲,我们只要能够创建于服务端相匹配的终结点,就能够实现正常的服务调用.在WCF客户端元数据架构体系中,利用MetadataExchangeClient可以获取服

WCF技术剖析之二:再谈IIS与ASP.NET管道

原文:WCF技术剖析之二:再谈IIS与ASP.NET管道 在2007年9月份,我曾经写了三篇详细介绍IIS架构和ASP.NET运行时管道的文章,深入介绍了IIS 5.x与IIS 6.0HTTP请求的监听与分发机制,以及ASP.NET运行时管道对HTTP请求的处理流程: [原创]ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI [原创]ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part I

WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果?

原文:WCF技术剖析之九:服务代理不能得到及时关闭会有什么后果? 我们想对WCF具有一定了解的人都会知道:在客户端通过服务调用进行服务调用过程中,服务代理应该及时关闭.但是如果服务的代理不等得到及时的关闭,到底具有怎样的后果?什么要关闭服务代理?在任何时候都需要关闭服务代理吗?是否有一些例外呢?本篇文章将会围绕着这些问题展开. 一.会话信道(Sessionful Channel) V.S. 数据报信道(Datagram Channel) WCF通过信道栈实现了消息的编码.传输及基于某些特殊功能对

WCF技术剖析之十一:异步操作在WCF中的应用(上篇)

原文:WCF技术剖析之十一:异步操作在WCF中的应用(上篇) 按照操作执行所需的资源类型,我们可以将操作分为CPU绑定型(CPU Bound)操作和I/O绑定型(I/O Bound)操作.对于前者,操作的执行主要利用CPU进行密集的计算,而对于后者,大部分的操作处理时间花在I/O操作处理,比如访问数据库.文件系统.网络资源等.对于I/O绑定型操作,我们可以充分利用多线程的机制,让多个操作在自己的线程并发执行,从而提高系统性能和响应能力.服务调用就是典型的I/O绑定型操作,所以多线程在服务调用中具