首页 > 代码库 > WCF探索之旅(四)——程序中WCF服务整合

WCF探索之旅(四)——程序中WCF服务整合

我们在之前的博客已经完成过实例,大家也看到了如何使用WCF服务:

添加服务引用——>输入服务地址——>实例化服务——>调用服务方法

 

那么今天为什么要再次说“程序中WCF服务整合”这个话题?

用过WebService的人都知道,随着服务的增多,管理WebService是一个非常繁重的工作。好了,今天我们的目标来了——让WCF服务变得整齐、有序、易管理!

 

首先,我们建立一个工厂类,这个工厂用来实例化我们的服务。这样做的好处是,所有的服务都是由工厂实例化的。

然后我们要建立一个公共的接口,这个接口继承所有的服务接口。这样做的好处是,所有的服务接口都可以用这个接口来代替。

 

好了,有了这两点,我们就可以利用多态+工厂来统一管理我们的服务了。

 

说了这么多理论,还是以我们程序猿的语言说更明了一些!

1、建立接口类IServices

	namespace <span style="font-family: SimSun; font-size: 10.5pt;">Modules.Interface</span>	{
	    [ServiceContract]
	    public interface IServices :
	        IUserSevice
	    {
	
	    }
	}

2、建立服务工厂ServiceFactory

	namespace Modules.Factory
	{
	    public  class ServiceFactory
	    {
			private static readonly SortedList<string, IServices> _serviceBusiness = new SortedList<string, IServices>();
			//获取接口
			public static IServices GetServiceBusiness(string endpointName)
			{
				IServices iServices;
				iServices = CreateWCFInterface(endpointName);
				if (_serviceBusiness.ContainsKey(endpointName)) {
					iServices = _serviceBusiness[endpointName];
				}
				else
				{
					if (true)
					{
						iServices = CreateWCFInterface(endpointName);
					}
					_serviceBusiness.Add(endpointName, iServices);
				}
					return iServices;
			}
			//获取WCF服务方法,使用代理工厂
			private static IServices CreateWCFInterface(string endpointName)
			{
			            return ServiceProxyFactory.Create<IServices>(endpointName);
			}
		
			//获取用户服务
			public static IUserSevice GetUserService(string endpointName)
			{
				return GetServiceBusiness(endpointName);
			}
		}
	}

3、建立代理工厂ServiceProxyFactory 

	namespace Modules.Factory.ServiceProxy
	{
	    public static class ServiceProxyFactory {
	        public static T Create<T>(string endpointName) {
	            if (string.IsNullOrEmpty(endpointName)) {
	                throw new ArgumentNullException("endpointName");
	            }
	            return (T)(new ServiceRealProxy<T>(endpointName).GetTransparentProxy());
	        }
	    }
	}

4、建立代理类RealProxy 

	namespace Modules.Factory.ServiceProxy
	{
		public class ServiceRealProxy<T> : RealProxy 
		{
			private readonly string _endpointName;
			public ServiceRealProxy(string endpointName): base(typeof(T)) 
			{
				if (string.IsNullOrEmpty(endpointName)) 
				{
					throw new ArgumentNullException("endpointName");
				}
				this._endpointName = endpointName;
			}
			//重写Invoke
			public override IMessage Invoke(IMessage msg) 
			{
				T channel = ChannelFactoryCreator.Create<T>(this._endpointName).CreateChannel();
				IMethodCallMessage methodCall = (IMethodCallMessage)msg;
				IMethodReturnMessage methodReturn = null;
				object[] copiedArgs = Array.CreateInstance(typeof(object), methodCall.Args.Length) as object[];
				methodCall.Args.CopyTo(copiedArgs, 0);
				try {
					object returnValue = http://www.mamicode.com/methodCall.MethodBase.Invoke(channel, copiedArgs);>5、建立通道工厂ChannelFactoryCreator

	namespace ICT.RCS.Modules.Factory.ServiceProxy
	{
	    internal static class ChannelFactoryCreator {
	        private static readonly Hashtable channelFactories = new Hashtable();
	        public static ChannelFactory<T> Create<T>(string endpointName) {
	            if (string.IsNullOrEmpty(endpointName)) {
	                throw new ArgumentNullException("endpointName");
	            }
	
	            ChannelFactory<T> channelFactory = null;
	            if (channelFactories.ContainsKey(endpointName)) {
	                channelFactory = channelFactories[endpointName] as ChannelFactory<T>;
	            }
	            if (channelFactory == null) {
	                channelFactory = new ChannelFactory<T>(endpointName);
	                lock (channelFactories.SyncRoot) {
	                    channelFactories[endpointName] = channelFactory;
	                }
	            }
	            return channelFactory;
	        }
	    }
	}

6、引入工厂dll

要想使用WCF,我们以前是必须添加服务引用,而添加服务引用VS就会自动生成一个APP.CONFIG的配置文件,这个文件中配置了服务的地址以及访问协议等内容。

现在,我们需要将上面的这些内容打包成dll并添加到引用。

7、配置app.config

		<configuration>
		  <runtime>
		    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
		      <probing privatePath="bin"/>
		    </assemblyBinding>
		  </runtime>
		  <system.serviceModel>
		    <behaviors>
		      <endpointBehaviors>
		        <behavior name="bhc">
		          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
		        </behavior>
		      </endpointBehaviors>
		    </behaviors>
		    <bindings>
		      <wsHttpBinding>
		        <binding name="WSHttpBinding_WcfService" closeTimeout="00:01:00"
		             openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
		             bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
		             maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
		             messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
		             allowCookies="false">
		          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647"
		              maxBytesPerRead="409600" maxNameTableCharCount="16384" />
		          <reliableSession ordered="true" inactivityTimeout="00:10:00"
		              enabled="false" />
		          <security mode="None">
		            <transport clientCredentialType="Windows" proxyCredentialType="None"
		                realm="" />
		            <message clientCredentialType="Windows" negotiateServiceCredential="true"
		                establishSecurityContext="true" />
		          </security>
		        </binding>
		      </wsHttpBinding>
		    </bindings>
		    <client>
		      <endpoint address="http://localhost:8080/UserManagerService.svc"
		                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_WcfService"
		                contract="wcfDemo.IServices" name="Service" />
		    </client>
		  </system.serviceModel>
	</configuration>

至此,我们的整合已经完成了。我们在需要用服务的地方使用ServiceFactory.GetUserService().AddUser(enUser);即可。不需要引入服务引用,不需要手动实例化,是不是方便了很多,灵活了很多!

 

如果现在有了新的服务需求,我们只需要

1、开发一个新的接口和实现

2、在IService接口中添加继承

3、更新服务

4、程序中直接调用ServiceFactory就可以“点”出它来

 

这篇博客中参考了其他人很多东西,也是一次尝试。如果大家在练习或者使用过程中遇到什么问题,咱们可以一起交流!

 

下一篇博客跟大家一起分享:WCFWebService的异同