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 <span style="font-family: SimSun; font-size: 10.5pt;">Modules.Interface</span>{ [ServiceContract] public interface IServices : IUserSevice { }}
2. Establish Service Factory servicefactory
Namespace modules. factory {public class servicefactory {Private Static readonly sortedlist <string, iservices> _ servicebusiness = new sortedlist <string, iservices> (); // obtain the public static iservices getservicebusiness (string endpointname) Interface) {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 <iservices> (endpointname);} // obtain the 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<T>(string endpointName) { if (string.IsNullOrEmpty(endpointName)) { throw new ArgumentNullException("endpointName"); } return (T)(new ServiceRealProxy<T>(endpointName).GetTransparentProxy()); } }}
4. Create proxy 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;} // rewrite invokepublic 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 = 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 }:\ n {1}", title, tiex. innerexception. message), tiex. innerexception);} else if (tiex. innerexception is faultexception) {Title = string. concat ("wcfexception", "faultexception", "internal method exception not handled"); throw new exception (string. format ("{0 }:\ n {1}", title, tiex. innerexception. message), tiex. innerexception);} else if (tiex. innerexception is communicationexception) {Title = string. concat ("wcfexception", "communicationexception", "network exception, check whether the address is correct"); throw new exception (string. format ("{0 }:\ n {1}", title, tiex. innerexception. message), tiex. innerexception);} else if (tiex. innerexception is timeoutexception) {Title = string. concat ("wcfexception", "timeoutexception", "connection timed out, check whether the network is normal"); throw new exception (string. format ("{0 }:\ n {1}", title, tiex. innerexception. message), tiex. innerexception) ;}} catch (exception ex) {Throw new exception (string. format ("unknown exception in WCF: \ n {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<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. 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
<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>
So far, our integration has been completed. We can use servicefactory. getuserservice (). adduser (enuser); where services are needed. There is no need to introduce service references and manual instantiation. Is it much more convenient and flexible!
If you have new service requirements
1. Develop a new interface and implementation
2. Add inheritance in the iservice Interface
3. Update Services
4. directly call servicefactory in the program to "point" it out.
This blog is also an attempt to refer to many other things. If you have any questions during your practice or usage, let's talk about them!
The next blog will share with you the similarities and differences between WCF and WebService.