Наличие обратного вызова WCF только для привязки, которая поддерживает его - PullRequest
1 голос
/ 08 сентября 2011

Я пытаюсь создать службу WCF с конечной точкой webHttpBinding (для клиентов Java) и конечной точкой netTcpBinding (для клиентов .NET).

С конечной точкой netTcpBinding я хотел бы иметь возможность использовать обратные вызовы для оповещения о событиях, но когда я пытаюсь настроить это, WCF жалуется, потому что служба также имеет конечную точку webHttpBinding, которая не ' t поддерживает обратные вызовы.

Есть ли способ использовать обратный вызов одной конечной точкой, но не другой?

1 Ответ

4 голосов
/ 08 сентября 2011

Нет, обязательная проверка подтвердит, что она может выполнить договор; если контракт является дуплексным (т. е. он указывает CallbackContract), но привязка не может выполнить дуплекс, то он будет выброшен во время проверки.

То, что вы можете сделать, это иметь базовый контракт, который используется конечной точкой webHttpBinding, и другой контракт (на этот раз дуплексный), полученный из первого, который используется конечной точкой netTcpBinding.

В приведенном ниже коде показан пример такой договоренности.

public class StackOverflow_7341463
{
    [ServiceContract]
    public interface ICalc
    {
        [OperationContract, WebGet]
        int Add(int x, int y);
        [OperationContract, WebGet]
        int Subtract(int x, int y);
        [OperationContract, WebGet]
        int Multiply(int x, int y);
        [OperationContract, WebGet]
        int Divide(int x, int y);
    }
    [ServiceContract(CallbackContract = typeof(ICalcNotifications))]
    public interface INotifyingCalc : ICalc
    {
        [OperationContract]
        void Connect();
        [OperationContract]
        void Disconnect();
    }
    [ServiceContract]
    public interface ICalcNotifications
    {
        [OperationContract(IsOneWay = true)]
        void OperationPerformed(string text);
    }
    public class Service : INotifyingCalc
    {
        static List<ICalcNotifications> clients = new List<ICalcNotifications>();

        #region ICalc Members

        public int Add(int x, int y)
        {
            this.NotifyOperation("Add", x, y);
            return x + y;
        }

        public int Subtract(int x, int y)
        {
            this.NotifyOperation("Subtract", x, y);
            return x - y;
        }

        public int Multiply(int x, int y)
        {
            this.NotifyOperation("Multiply", x, y);
            return x * y;
        }

        public int Divide(int x, int y)
        {
            this.NotifyOperation("Divide", x, y);
            return x / y;
        }

        #endregion

        #region INotifyingCalc Members

        public void Connect()
        {
            var callback = OperationContext.Current.GetCallbackChannel<ICalcNotifications>();
            clients.Add(callback);
        }

        public void Disconnect()
        {
            var callback = OperationContext.Current.GetCallbackChannel<ICalcNotifications>();
            clients.Remove(callback);
        }

        #endregion

        private void NotifyOperation(string operationName, int x, int y)
        {
            foreach (var client in clients)
            {
                client.OperationPerformed(string.Format("{0}({1}, {2})", operationName, x, y));
            }
        }
    }
    class MyCallback : ICalcNotifications
    {
        public void OperationPerformed(string text)
        {
            Console.WriteLine("Operation performed: {0}", text);
        }
    }
    public static void Test()
    {
        string baseAddressTcp = "net.tcp://" + Environment.MachineName + ":8008/Service";
        string baseAddressHttp = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddressHttp), new Uri(baseAddressTcp));
        host.AddServiceEndpoint(typeof(ICalc), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
        host.AddServiceEndpoint(typeof(INotifyingCalc), new NetTcpBinding(SecurityMode.None), "");
        host.Open();
        Console.WriteLine("Host opened");

        var factory = new DuplexChannelFactory<INotifyingCalc>(
            new InstanceContext(new MyCallback()),
            new NetTcpBinding(SecurityMode.None),
            new EndpointAddress(baseAddressTcp));
        var proxy = factory.CreateChannel();
        proxy.Connect();
        Console.WriteLine("Proxy connected");

        Console.WriteLine(new WebClient().DownloadString(baseAddressHttp + "/Add?x=4&y=7"));
        Console.WriteLine(new WebClient().DownloadString(baseAddressHttp + "/Multiply?x=44&y=57"));
        Console.WriteLine(new WebClient().DownloadString(baseAddressHttp + "/Divide?x=432&y=16"));

        proxy.Disconnect();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();

        ((IClientChannel)proxy).Close();
        factory.Close();
        host.Close();
    }
}
...