WCF (6) of the in-depth analysis of service contracts [next]

I. Introduction

   In a previous blog post, we analyzed how to operate heavy load in WCF, the main point is achieved through the server ServiceContract Name property to define an alias for the operator to make the operation were not the same, but the client is through rewrite the way the client proxy class to achieve. Share inheritance contract will be implemented in this blog post.

Second, inherit the implementation of WCF service contract restrictions

   Firstly, under the WCF traditional way to achieve a contract inheritance, let's look at how the case was achieved without any modification of the contract inherited by a simple WCF application. We still follow the previous steps to achieve this WCF applications.

  • Step one: Implementing WCF Service

   Here, we define two service contract, is the inheritance of the relationship between them, the specific implementation code as follows:

Service contract 1 //
2 [the ServiceContract]
. 3 ISimpleInstrumentation public interface
. 4 {
. 5 [the OperationContract]
. 6 WriteEventLog String ();
. 7}
. 8
. 9 // service contract, the service contract inherited ISimpleInstrumentation
10 [the ServiceContract]
. 11 public interface ICompleteInstrumentation: ISimpleInstrumentation
{12 is
13 is [the OperationContract]
14 IncreatePerformanceCounter String ();
15}

  Above it defines two interfaces as a service contract, which ICompleteInstrumentation inherited ISimpleInstrumentation. It should be noted that: Although ICompleteInstrumentation inherited from ISimpleteInstrumentation, but used in ISimpleInstrumentation in ServiceContractAttribute not be inherited ICompleteInstrumentation, because AttributeUsage on top of it Inherited property is set to false, on behalf of ServiceContractAttribute can not be derived interface inheritance. ServiceContractAttribute specific definitions are as follows:

[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Interface, Inherited = false,
AllowMultiple = false)]
public sealed class ServiceContractAttribute : Attribute

  Next, to achieve the corresponding service specific implementation code as follows:

// 实现ISimpleInstrumentation契约
public class SimpleInstrumentationService : ISimpleInstrumentation
{
#region ISimpleInstrumentation members
public string WriteEventLog()
{
return "Simple Instrumentation Service is Called";
}
#endregion
}

// 实现ICompleteInstrumentation契约
public class CompleteInstrumentationService: SimpleInstrumentationService, ICompleteInstrumentation
{
public string IncreatePerformanceCounter()
{
return "Increate Performance Counter is called";
}
}

  Above, in order to reuse code, CompleteInstrumentationService inherited from SimpleInstrumentationService, thereby eliminating the need to redefine the method WriteEventLog.

  • Step Two: Implement a service host

   After the completion of the service is defined, now look to achieve a host of services, where the service host is a console application, specific implementation code and the code of similar previous chapters, specific implementation code as follows:

// implement the service host 1, the host console WCF service program
2 Program class
. 3 {
. 4 static void the Main (String [] args)
. 5 {
. 6 the using (= the ServiceHost new new Host the ServiceHost (typeof (WCFService.CompleteInstrumentationService)) )
. 7 {
. 8 host.Opened + = the delegate
. 9 {
10 Console.WriteLine ( "Started-Service");
. 11};
12 is
13 is open a communication channel //
14 host.Open ();
15 Console.Read ();
16}
. 17
18}
19}

  Profile information corresponding to the host program is as follows:

<Configuration>
<system.serviceModel>
<Behaviors>
<serviceBehaviors>
<behavior name = "metadataBehavior">
<httpGetEnabled the serviceMetadata = "to true" />
</ behavior>
</ serviceBehaviors>
</ Behaviors>
<Services>
<! - name property service label is necessary, and must be specified as the service type, specify the format: namespace service class name ->
<! - more information can refer to MSDN: http: //msdn.microsoft.com/zh -CN / Library / ms731303 (V = vs.110) .aspx ->
<-Service name = "WCFService.CompleteInstrumentationService" the behaviorConfiguration = "metadataBehavior">
<Endpoint address = "MEX" Binding = "mexHttpBinding" Contract = "WCFService. ICompleteInstrumentation "/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:9003/instrumentationService/"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>

  • Step three: implementation of the client

   Finally, it is to achieve our client to access a service, here first run with administrator privileges to the host application that runs WCFServiceHostByConsoleApp.exe executable with administrator privileges. After running successfully, you will see the service startup success message in the console, the specific operating results as shown below:

  Then the client by way of adding a service reference to add service reference, this time it must be remembered, must first run a hosting service, so as to add the service reference window, enter the address: http: // localhost: 9003 / instrumentationService / order get metadata information services. After successfully added, svcutil.exe tools in addition to previously generates a corresponding client proxy class for us, but also automatically add profile information, but also add a reference System.ServiceModel.dll for us. Here are our tools generate code:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference.ICompleteInstrumentation")]
public interface ICompleteInstrumentation {

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISimpleInstrumentation/WriteEventLog", ReplyAction="http://tempuri.org/ISimpleInstrumentation/WriteEventLogResponse")]
string WriteEventLog();

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISimpleInstrumentation/WriteEventLog", ReplyAction="http://tempuri.org/ISimpleInstrumentation/WriteEventLogResponse")]
System.Threading.Tasks.Task<string> WriteEventLogAsync();

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICompleteInstrumentation/IncreatePerformanceCounter", ReplyAction="http://tempuri.org/ICompleteInstrumentation/IncreatePerformanceCounterResponse")]
string IncreatePerformanceCounter();

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICompleteInstrumentation/IncreatePerformanceCounter", ReplyAction="http://tempuri.org/ICompleteInstrumentation/IncreatePerformanceCounterResponse")]
System.Threading.Tasks.Task<string> IncreatePerformanceCounterAsync();
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface ICompleteInstrumentationChannel : ClientConsoleApp.ServiceReference.ICompleteInstrumentation, System.ServiceModel.IClientChannel {
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class CompleteInstrumentationClient : System.ServiceModel.ClientBase<ClientConsoleApp.ServiceReference.ICompleteInstrumentation>, ClientConsoleApp.ServiceReference.ICompleteInstrumentation {

public CompleteInstrumentationClient() {
}

public CompleteInstrumentationClient(string endpointConfigurationName) :
base(endpointConfigurationName) {
}

public CompleteInstrumentationClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}

public CompleteInstrumentationClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}

public CompleteInstrumentationClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress) {
}

public string WriteEventLog() {
return base.Channel.WriteEventLog();
}

public System.Threading.Tasks.Task<string> WriteEventLogAsync() {
return base.Channel.WriteEventLogAsync();
}

public string IncreatePerformanceCounter() {
return base.Channel.IncreatePerformanceCounter();
}

public System.Threading.Tasks.Task<string> IncreatePerformanceCounterAsync() {
return base.Channel.IncreatePerformanceCounterAsync();
}
}

  In the service side, we define a service contract inheritance hierarchy, and discloses a EndPoint is ICompleteInstrumentation contract. But the client, we add service reference by way of the generated service contract but not the inheritance relationship can be seen in the above places in the code marked red, in which case the client proxy class only defines a service contract, the service contract defines all of the Operation. At this time, the client implementation code is shown below:

1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Console.WriteLine("---Use Genergate Client by VS Tool to call method of WCF service---");
6 using (CompleteInstrumentationClient proxy = new CompleteInstrumentationClient())
7 {
8 Console.WriteLine(proxy.WriteEventLog());
9 Console.WriteLine(proxy.IncreatePerformanceCounter());
10 }
11
12 Console.Read();
13 }
14 }

  As can be seen from the above code. Although we now call the service can be done by calling CompleteInstrumentationClient proxy class, but we hope that the client proxy class inheritance structure also has a contractual relationship.

Third, to achieve the client's contract level

   Now, the auto-generated code can not complete our needs, then we can define your own proxy class by way of custom.

  • The first step is to define the client's Service Contract. Specific custom code is as follows:

ClientConsoleApp namespace. 1
2 {
. 3 // custom service contract with the server to keep it as a result of inheritance
. 4 [the ServiceContract]
. 5 ISimpleInstrumentation public interface
. 6 {
. 7 [the OperationContract]
. 8 WriteEventLog String ();
. 9}
10
. 11 [the ServiceContract]
public interface ICompleteInstrumentation 12 is: ISimpleInstrumentation
13 is {
14 [the OperationContract]
15 IncreatePerformanceCounter String ();
16}
. 17}

  • Step Two: Custom two proxy class, specific implementation code as follows:

// 自定义代理类
public class SimpleInstrumentationClient : ClientBase<ICompleteInstrumentation>, ISimpleInstrumentation
{
#region ISimpleInstrumentation Members
public string WriteEventLog()
{
return this.Channel.WriteEventLog();
}
#endregion
}

public class CompleteInstrumentationClient:SimpleInstrumentationClient, ICompleteInstrumentation
{
public string IncreatePerformanceCounter()
{
return this.Channel.IncreatePerformanceCounter();
}
}

  Configuration file corresponding to the following modifications:

<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="MetadataExchangeHttpBinding_ICompleteInstrumentation1">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:9003/instrumentationService/mex"
binding="wsHttpBinding" bindingConfiguration="MetadataExchangeHttpBinding_ICompleteInstrumentation1"
contract="ClientConsoleApp.ICompleteInstrumentation" name="MetadataExchangeHttpBinding_ICompleteInstrumentation1" />
</client>
</system.serviceModel>
</configuration>

  • The third step: to implement the client service call, this time from the proxy class may be defined to respectively correspond to two service contract calling operation by two specific implementation code as follows:

1 class Program
2 {
3 static void Main(string[] args)
4 {
5 using (SimpleInstrumentationClient proxy1 = new SimpleInstrumentationClient())
6 {
7 Console.WriteLine(proxy1.WriteEventLog());
8 }
9 using (CompleteInstrumentationClient proxy2 = new CompleteInstrumentationClient())
10 {
11 Console.WriteLine(proxy2.IncreatePerformanceCounter());
12 }
13
14 Console.Read();
15 }
16 }

  Thus, by way of rewriting the proxy class, the client can fully object-oriented approach to call a method of the service contract, specific operational results as shown below:

  Also, if you do not want to define two proxy class, you can also call for service contracts in the following way, specific implementation steps:

  • The first step: the same is achieved with a service contract inheritance, the specific implementation code as before.

// custom service contract with the server to keep it as a result of inheritance
[the ServiceContract]
public interface ISimpleInstrumentation
{
[the OperationContract]
String WriteEventLog ();
}

[the ServiceContract]
public interface ICompleteInstrumentation: ISimpleInstrumentation
{
[the OperationContract]
String IncreatePerformanceCounter ();
}

  • Step two: modify the configuration file. The client profile is modified as follows:

<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:9003/instrumentationService/mex"
binding="mexHttpBinding" contract="ClientConsoleApp.ISimpleInstrumentation"
name="ISimpleInstrumentation" />
<endpoint address="http://localhost:9003/instrumentationService/mex"
binding="mexHttpBinding" contract="ClientConsoleApp.ICompleteInstrumentation"
name="ICompleteInstrumentation" />
</client>
</system.serviceModel>
</configuration>

  • The third step: implementation of the client code. Specific implementation code is shown below:

1 class Program
2 {
3 static void Main(string[] args)
4 {
5 using (ChannelFactory<ISimpleInstrumentation> simpleChannelFactory = new ChannelFactory<ISimpleInstrumentation>("ISimpleInstrumentation"))
6 {
7 ISimpleInstrumentation simpleProxy = simpleChannelFactory.CreateChannel();
8 using (simpleProxy as IDisposable)
9 {
10 Console.WriteLine(simpleProxy.WriteEventLog());
11 }
12 }
13 using (ChannelFactory<ICompleteInstrumentation> completeChannelFactor = new ChannelFactory<ICompleteInstrumentation>("ICompleteInstrumentation"))
14 {
15 ICompleteInstrumentation completeProxy = completeChannelFactor.CreateChannel();
16 using (completeProxy as IDisposable)
17 {
18 Console.WriteLine(completeProxy.IncreatePerformanceCounter());
19 }
20 }
21
22 Console.Read();
23 }
24 }

  In fact, the above principles and implementation code defines two client proxy class is the same, but this time the proxy class on the client calling code implementation. As can be seen by the above code, to communicate, primarily to create a communication channel with the server, i.e. Channel, the above direct to create a communication channel through ChannelFactory <T> of CreateChannel method, and by defining a proxy class is through ClientBase <T> of the channel property to obtain the current communication channel, which implement ClientBase class itself also creates a channel by ChannelFactory.CreateChannel method, and then assign the created channels to channel property, for the outside channel acquisition created. So the principle of two implementations are the same, and by automatically generated proxy class is the same principle.

IV Summary

  Here, the contents of this article share is over, this paper to call for service contracts inherited by way of a custom agent class. Its implementation ideas and realization of ideas on a heavy-duty operation is the same, since the client code automatically generated class can not meet the demand, it will only extend the custom. This sharing service contract will come to an end, behind the blog post continued to share data contracts in WCF.

 

Transfer: https: //www.cnblogs.com/zhili/p/MSMQ.html, Author: Learning hard.

If infringement, please contact me to delete!

Guess you like

Origin blog.csdn.net/IT_0802/article/details/91501851