WCF exploration journey (4) -- Integration of WCF services in programs
We have completed examples in our previous blog, and we have also seen how to use the WCF Service:
Add service reference --> enter service address --> instantiate service --> call service method
So why do we need to talk about the topic "program-based WCF Service integration" again today?
People who have used WebService know that managing WebService is a very heavy task as the number of services increases. Now, our goal is to make the WCF Service neat, orderly, and easy to manage!
First, we create a factory class to instantiate our services. The advantage of doing so is that all services are instantiated by the factory.
Then we need to create a public interface that inherits all service interfaces. The advantage of this is that all service interfaces can be replaced by this interface.
Well, with these two points, we can use polymorphism + factory to manage our services in a unified manner.
With so many theories, we are still more clear in the language of our programmers!
1. Create an interface class IServices
namespace Modules.Interface{ [ServiceContract] public interface IServices : IUserSevice { }}
2. Establish Service Factory ServiceFactory
Namespace Modules. Factory {public class ServiceFactory {private static readonly SortedList
_ ServiceBusiness = new SortedList
(); // Obtain the 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;} // obtain the WCF Service method. Use the proxy factory private static IServices CreateWCFInterface (string endpointName) {return ServiceProxyFactory. create
(EndpointName) ;}// get the user service public static IUserSevice GetUserService (string endpointName) {return GetServiceBusiness (endpointName );}}}
3. Create a proxy factory ServiceProxyFactory
namespace Modules.Factory.ServiceProxy{ public static class ServiceProxyFactory { public static T Create
(string endpointName) { if (string.IsNullOrEmpty(endpointName)) { throw new ArgumentNullException(endpointName); } return (T)(new ServiceRealProxy
(endpointName).GetTransparentProxy()); } }}
4. Create proxy RealProxy
Namespace Modules. Factory. ServiceProxy {public class ServiceRealProxy
: RealProxy {private readonly string _ endpointName; public ServiceRealProxy (string endpointName): base (typeof (T) {if (string. isNullOrEmpty (endpointName) {throw new ArgumentNullException (endpointName);} this. _ endpointName = endpointName;} // rewrite Invokepublic override IMessage Invoke (IMessage msg) {T channel = ChannelFactoryCreator. create
(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 = methodCall. methodBase. invoke (channel, copiedArgs); methodReturn = new ReturnMessage (returnValue, copiedArgs, copiedArgs. length, methodCall. logicalCallContext, methodCall); (ICommunicationObject) channel ). close ();} catch (TargetInvocationException tiEx) {string title; if (tiEx. innerException is NotSupportedException) {title = string. concat (wcfexception, NotSupportedException, WCF Service Contract Exception); throw new Exception (string. format ({0 }:{ 1}, title, tiEx. innerException. message), tiEx. innerException);} else if (tiEx. innerException is FaultException) {title = string. concat (wcfexception, FaultException, an internal error occurred in the method); throw new Exception (string. format ({0 }:{ 1}, title, tiEx. innerException. message), tiEx. innerException);} else if (tiEx. innerException is CommunicationException) {title = string. concat (wcfexception, CommunicationException, network Exception, please check whether the address is correct); throw new Exception (string. format ({0 }:{ 1}, title, tiEx. innerException. message), tiEx. innerException);} else if (tiEx. innerException is TimeoutException) {title = string. concat (wcfexception, TimeoutException, connection timeout, please check whether the network is normal); throw new Exception (string. format ({0 }:{ 1}, title, tiEx. innerException. message), tiEx. innerException) ;}} catch (Exception ex) {throw new Exception (string. format (unknown exception in WCF: {0}, ex. message), ex);} finally {(ICommunicationObject) channel ). abort () ;}return methodReturn ;}}}
5. Establish channel factory ChannelFactoryCreator
namespace ICT.RCS.Modules.Factory.ServiceProxy{ internal static class ChannelFactoryCreator { private static readonly Hashtable channelFactories = new Hashtable(); public static ChannelFactory
Create
(string endpointName) { if (string.IsNullOrEmpty(endpointName)) { throw new ArgumentNullException(endpointName); } ChannelFactory
channelFactory = null; if (channelFactories.ContainsKey(endpointName)) { channelFactory = channelFactories[endpointName] as ChannelFactory
; } if (channelFactory == null) { channelFactory = new ChannelFactory
(endpointName); lock (channelFactories.SyncRoot) { channelFactories[endpointName] = channelFactory; } } return channelFactory; } }}
6. Introduce factory dll
To use WCF, we used to have to add a service reference, and adding a service reference VS will automatically generate an APP. CONFIG configuration file, which contains the service address and access protocol.
Now, we need to package the above content into a dll and add it to the reference.
7. Configure app. config