调用动态添加到服务契约的操作

Posted

技术标签:

【中文标题】调用动态添加到服务契约的操作【英文标题】:Call an operation that was dynamically added to the service contract 【发布时间】:2012-03-25 22:50:51 【问题描述】:

我有一个 WCF 服务合同(比如 IService1),我会动态地向其中添加一个操作,如 here 所述。 当我只有一个 IService1 透明代理和通过 ClientChannelFactory 创建的 IClientChannel 时,如何从客户端调用动态添加的操作?

更新

我可以使用this method从ChannelFactory返回的透明代理获取RealProxy。

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

是否可以使用虚假消息调用realyProxy.Invoke(IMessage) 来欺骗代理调用动态添加的方法?

【问题讨论】:

【参考方案1】:

用这个替换 GeneratePingMethod:

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);
    

并像这样创建您的客户:

// 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());

    

【讨论】:

这不是一个可接受的解决方案,因为我希望该解决方案可在各种服务中重复使用,我只想将它作为一种行为挂钩。我不喜欢我的所有服务接口都必须从定义了附加方法的接口继承的想法。 “我不喜欢我的所有服务接口都必须继承自定义附加方法的接口的想法。”我提出的解决方案没有对您施加这种约束。只需拥有您的 Service 接口,当您需要动态 WCF 操作契约时,只需使用新操作契约的定义扩展您的接口即可。 但是您将新的扩展接口强加给我的客户。我不希望我的客户端 channelfactory 创建 IExtendedInterface 的实例,但仍使用原始实例。当然必须是通过扩展 ChannelFactory(例如添加行为)来实现这一点的方法,我认为通过扩展 RealProxy 等来实现。

以上是关于调用动态添加到服务契约的操作的主要内容,如果未能解决你的问题,请参考以下文章

动态调用webservice

将方法添加到调用“super”的动态创建的类

使用 JointCode.Shuttle 动态注册 / 注销服务

在django中动态添加参数到queryset过滤器调用[重复]

Flutter:如何调用本地 JSON 数据并动态添加到标签栏?

C#中Winform动态调用Webservice的方法(转)