Operation Overloading
WCF Service does not explicitly support the operation overloading ,the following snippet code will throw a exception at the service host load time:
[ServiceContract]
interface ICalculator
{
[OperationContract]
int Add(int x, int y);[OperationContract]
double Add(double x, double y);
}
the developer can avoid this exception but without updating the operation name by aliasing the operation name using Name property of OperationContract attribute. the following snippet shows what we should do:
[ServiceContract]
interface ICalculator
{
[OperationContract(Name="AddInt")]
int Add(int x, int y);[OperationContract(Name="AddDouble")]
double Add(double x, double y);
}
as we see here, we do fix the overloading problem at the service side with the help of the Name property, but how does the corresponding client perform this? unfortunately it does not work as we thought, just working with the alias name of the operation as following:
public interface ICalculator {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICalculator/AddInt",
ReplyAction="http://tempuri.org/ICalculator/AddIntResponse")]
int AddInt(int x, int y);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ICalculator/AddDouble",
ReplyAction="http://tempuri.org/ICalculator/AddDoubleResponse")]
double AddDouble(double x, double y);
}
as see here ,which is not our so-called overloading, but we can restore the overloading hierarchy on the client side manually as following snippet shows:
[ServiceContract]
public interface ICalculator {
[OperationContract(Name="AddInt")]
int Add(int x, int y);
[OperationContract(Name="AddDouble")]
double Add(double x, double y);
}
Do what we have done on the server side for the client using the name property(the name on the client side must match up with the name at on the server side), and this is not enough, we also should update the client proxy as following:
public int AddInt(int x, int y) {
return base.Channel.Add(x, y);
}
public double AddDouble(double x, double y) {
return base.Channel.Add(x, y);
}
so what we have done on the cilent side makes the client be overloading. so amazing!
Contract Inheritance
Service contract can inherit from other Service contracts, but the ServiceContract attribute is not inheritable, so every service contract muct explicitly apply the ServiceContract attribute.the following code shows how service contract inheritance works:
[ServiceContract]
interface ISimpleCalculator
{
[OperationContract]
double Add(double x, double y);
}[ServiceContract]
interface ICalculator:ISimpleCalculator
{
[OperationContract]
double Mutiply(double x, double y);
}public class CalculatorService:ICalculator
{
public double Mutiply(double x, double y)
{
return x*y;
}public double Add(double x, double y)
{
return x = y;
}
}
the host can expose a single endpoint for the bottom contract interface in the hierarchy.the following code is the host endpoint configuration:
<endpoint address="http://localhost:8080/calculatorService"
binding="wsHttpBinding"
contract="WCFOO.Server.ICalculator">
</endpoint>
as we supposed, host only exposes a single endpoint and contract is the bottom contract in the hierarchy.
as the same as we made about the operation overloading above,this is about the inheritance on the server side, and how does it work on the client side, as unfortunate as the operation overloading does on the client side, the inheritance hierarchy is not maintained on the client side. it becomes to be a flattened hierarchy.
client code for contract:
[ServiceContract]
public interface ICalculator {
[OperationContract(Action="http://tempuri.org/ISimpleCalculator/Add",
ReplyAction="http://tempuri.org/ISimpleCalculator/AddResponse")]
double Add(double x, double y);
[OperationContract(Action="http://tempuri.org/ICalculator/Mutiply",
ReplyAction="http://tempuri.org/ICalculator/MutiplyResponse")]
double Mutiply(double x, double y);
}
as we see, the operations use the Action and ReplyAction to find their real contract(here i didnot specify the namespace of the service so it’s the default namespace)
part of client code for service proxy:
public double Add(double x, double y) {
return base.Channel.Add(x, y);
}
public double Mutiply(double x, double y) {
return base.Channel.Mutiply(x, y);
}
so disappointed, there is no sign showing the inheritance hierarchy, but we can also restore the client code to make the client work like what we want as we did about the operation overloading.
we can add the hierachy manually as the client code:
[ServiceContract]
public interface ISimpleCalculator
{
[OperationContract]
double Add(double x, double y);
}[ServiceContract]
public interface ICalculator : ISimpleCalculator
{
[OperationContract]
double Mutiply(double x, double y);
}
public partial class SimpleCalculatorClient : ClientBase<ISimpleCalculator>,
ISimpleCalculator
{
public double Add(double x, double y)
{
return this.Channel.Add(x, y);
}
}public interface ICalculatorChannel : ICalculator, IClientChannel {
}
public partial class CalculatorClient : ClientBase<ICalculator>,
ICalculator
{
public CalculatorClient() {
}
public double Add(double x, double y) {
return base.Channel.Add(x, y);
}
public double Mutiply(double x, double y) {
return base.Channel.Mutiply(x, y);
}
}
and the client configuration should be changed simultaneously exposing two endpoints.
<client>
<endpoint address="http://localhost:8080/calculatorService"
binding="wsHttpBinding"
contract="WCFOO.Client.CalculatorService.ICalculator" >
</endpoint>
<endpoint address="http://localhost:8080/calculatorService"
binding="wsHttpBinding"
contract="WCFOO.Client.CalculatorService.ISimpleCalculator" >
</endpoint>
</client>
but the endpoint for server is still a single one without any changes.
late again today, i do not want to stay up here, this is not complete and leave it tomorrow.