Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Someone asked me if it’s possible to add a Ping method to every service contract without repeatedly defining it in each service contract? The answer is yes & and it’s fairly simply too.
Here I have a LoginService, which require that implicit Ping method (DateTime Ping(){})like all other service.
[ServiceContract]
class LoginService
{
[OperationContract]
public bool Login(string userName, string password)
{
return true;
}
}
This is how you would configure your host for these implicit methods.
class Program
{
static void Main(string[] args)
{
var sh = new ServiceHost(typeof(LoginService), new Uri("https://localhost:9001"));
GeneratePingMethod(sh);
sh.Open();
Console.ReadLine();
sh.Close();
}
}
Please note “GeneratePingMethod” adds the Ping method to every endpoint. I’m simply creating the operation using the WCF description API and adding it into the description tree. PingImplementationBehavior plugs in a custom OperationInvoker which calls the actual Ping implementation.
private static void GeneratePingMethod(ServiceHost sh)
{
foreach (var endpoint in sh.Description.Endpoints)
{
var cd = endpoint.Contract;
var od = new OperationDescription("Ping", cd);
var inputMsg = new MessageDescription(cd.Namespace + cd.Name + "/Ping", MessageDirection.Input);
var outputMsg = new MessageDescription(cd.Namespace + cd.Name + "/PingResponse", MessageDirection.Output);
var retVal = new MessagePartDescription("PingResult", cd.Namespace); ;
retVal.Type = typeof(DateTime);
outputMsg.Body.ReturnValue = retVal;
od.Messages.Add(inputMsg);
od.Messages.Add(outputMsg);
od.Behaviors.Add(new DataContractSerializerOperationBehavior(od));
od.Behaviors.Add(new PingImplementationBehavior());
cd.Operations.Add(od);
}
}
class PingImplementationBehavior : IOperationBehavior
{
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{ }
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{ }
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Invoker = new PingInvoker();
}
public void Validate(OperationDescription operationDescription)
{ }
}
Again a fairly simple invoker which is tightly coupled to the signature of Ping method.
class PingInvoker : IOperationInvoker
{
public object[] AllocateInputs()
{
return new object[0];
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
outputs = new object[0];
return Ping();
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
throw new NotImplementedException();
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
throw new NotImplementedException();
}
public bool IsSynchronous
{
get { return true; }
}
public static DateTime Ping()
{
return DateTime.Now;
}
}
Originally posted by Zulfiqar Ahmed on 5 February 2010 here https://www.zamd.net/2010/02/05/AddingDynamicMethodsToAWCFService.aspx