0

I have a WCF service contract (say IService1) to which I dynamically add an operation like described here. How could I call a dynamically added operation from the client-side when all I have is an IService1 transparent proxy and the IClientChannel created via the ClientChannelFactory?

Update

I can get the RealProxy from the transparent proxy returned from the ChannelFactory using this method.

var realProxy = System.Runtime.Remoting.RemotingServices.GetRealProxy( transparentProxy );

Would it be possible to call realyProxy.Invoke(IMessage) with a fake message to trick the proxy into calling the dynamically added method?

Community
  • 1
  • 1
m0sa
  • 10,712
  • 4
  • 44
  • 91

1 Answers1

0

Replace the GeneratePingMethod with this one:

private static void GenerateNewPingMethod(ServiceHost sh)
{
    foreach (var endpoint in sh.Description.Endpoints)
    {

        ContractDescription contract = endpoint.Contract;

        OperationDescription operDescr = new OperationDescription("Ping", contract);

        MessageDescription inputMsg = new MessageDescription(contract.Namespace + contract.Name + "/Ping", MessageDirection.Input);

        MessageDescription outputMsg = new MessageDescription(contract.Namespace + contract.Name + "/PingResponse", MessageDirection.Output);

        MessagePartDescription retVal = new MessagePartDescription("PingResult", contract.Namespace);

        retVal.Type = typeof(DateTime);

        outputMsg.Body.WrapperName = "PingResponse";
        outputMsg.Body.WrapperNamespace = contract.Namespace;
        outputMsg.Body.ReturnValue = retVal;


        operDescr.Messages.Add(inputMsg);
        operDescr.Messages.Add(outputMsg);
        operDescr.Behaviors.Add(new DataContractSerializerOperationBehavior(operDescr));
        operDescr.Behaviors.Add(new PingImplementationBehavior());
        contract.Operations.Add(operDescr);
    }
}

and create your clients as such:

// this is your base interface
[ServiceContract]
public interface ILoginService
{
    [OperationContract(Action = "http://tempuri.org/LoginService/Login", Name = "Login")]
    bool Login(string userName, string password);
}

[ServiceContract]
public interface IExtendedInterface : ILoginService
{
    [OperationContract(Action = "http://tempuri.org/LoginService/Ping", Name="Ping")]
    DateTime Ping();
}


class Program
{
    static void Main(string[] args)
    {
        IExtendedInterface channel = null;
        EndpointAddress endPointAddr = new EndpointAddress("http://localhost/LoginService");
        BasicHttpBinding binding = new BasicHttpBinding();

        channel = ChannelFactory<IExtendedInterface>.CreateChannel(binding, endPointAddr);

        if (channel.Login("test", "Test"))
        {
            Console.WriteLine("OK");
        }
        DateTime dt = channel.Ping();

        Console.WriteLine(dt.ToString());

    }
}
CSharpenter
  • 722
  • 8
  • 21
  • This is not an acceptable solution, since I want the solution to be reusable across various services, I just want to hook it in as a behavior. I don't like the idea that all my service interfaces must inherit from the interface on which the additional method is defined. – m0sa Mar 08 '12 at 17:44
  • "I don't like the idea that all my service interfaces must inherit from the interface on which the additional method is defined." My proposed solution is not imposing on you this constraint. Simply have your Service interfaces, and when you need your dynamic WCF operation contract, just extend your interface with the definition of the new operation contract. – CSharpenter Mar 08 '12 at 19:17
  • But you impose your new extended interface to my client. I don't want my client channelfactory to create an instance of the IExtendedInterface, but to still use the original one. The surely must be a way of accomplishing this by extending the ChannelFactory (e.g. adding a behavior), I figured by extending the RealProxy etc. – m0sa Mar 08 '12 at 21:03