Могу ли я использовать дуплексную привязку WCF для ретрансляции сообщений? - PullRequest
1 голос
/ 04 августа 2009

У меня есть клиентское приложение, сервер и другой клиент, давайте называть его сторонним. У меня есть интерфейс обратного вызова как часть моего контракта, который реализуется как третьей стороной, так и клиентом.

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

Ответы [ 4 ]

3 голосов
/ 05 августа 2009

Да, вы можете это сделать.

Самый простой способ - реализовать свой сервис как сервис PerSession и захватить контекст обратного вызова при инициализации / создании. Обычно я добавляю объект службы (который на самом деле представляет соединение в этой точке) к внутреннему базовому объекту.

Затем, когда вы получаете сообщение от клиента, вы можете позвонить любому из сервисных объектов (не по контракту) и внутренне перенаправить данные на связанный клиент.

Это довольно минимальная реализация концепции без обработки исключений и довольно плохой дизайн (статический класс BAD!). Я не проверял это, но принципы должны сохраняться, даже если я пропустил пересечение i или расставление точек t. В этом примере также перенаправляются вызовы всем клиентам, но выбор отдельного клиента происходит по той же базовой схеме.

Попытка сделать это с помощью одноэлементной службы будет более трудной, и служба для каждого вызова, очевидно, не будет работать:)

[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IContract
{
    [OperationContract(IsOneWay = true)]
    void SendTheData(string s);
}

public interface ICallback
{
    [OperationContract(IsOneWay = true)]
    void ForwardTheData(string s);
}

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.PerSession)]
public class ServiceConnection : IContract
{
    private ICallback m_callback;

    public ServiceConnection()
    {
        m_callback = OperationContext.Current.GetCallbackChannel<ICallback>();
        ServiceCore.Add(this);
    }

    public void SendTheData(string s)
    {
        ServiceCore.DataArrived(s);
    }

    public void SendToClient(string s)
    {
        m_callback.ForwardTheData(s);
    }
}

static public class ServiceCore
{
    static private List<ServiceConnection> m_connections = new List<ServiceConnection>();


    public static void DataArrived(string s)
    {
        foreach(ServiceConnection conn in m_connections)
        {
            conn.SendTheData(s);
        }
    }

    public static void Add(ServiceConnection connection)
    {
        m_connections.Add(connection);
    }
}
0 голосов
/ 06 августа 2009

Я думаю, что нашел решение ..

Вот ссылка. http://msdn.microsoft.com/en-us/magazine/cc163537.aspx

Попробуйте взглянуть на рисунок 6. Вот чего я пытаюсь достичь.

0 голосов
/ 04 августа 2009

Я не совсем понимаю, что вы на самом деле спрашиваете здесь ... но я все равно попытаюсь дать несколько советов.

Передача сообщений или маршрутизация не очень хорошо поддерживаются в WCF в .NET 3.5 - инфраструктура есть, но все еще предстоит много работы, чтобы настроить ее вручную.

Лучшее введение, которое я знаю в этой теме для WCF в .NET 3.5, - это статья Мишеля Леру Бустаманте, состоящая из двух частей, в журнале MSDN:

В части 2 есть раздел о дуплексных маршрутизаторах - это поможет вам в ваших поисках вообще?

WCF в .NET 4.0 обещает обеспечить дополнительную поддержку маршрутизации - будет базовый класс RoutingService, который можно использовать для написания сервисов маршрутизации, и он позволит настраивать маршрутизацию на основе контента или метаданных - что угодно это то, что вам нужно.

.NET 4.0 планируется выпустить чуть позже в этом году (2009) - надеюсь! Так что пока это еще будущее, оно выглядит радужным!

Марк

0 голосов
/ 04 августа 2009

Из краткого прочтения документации по сервису Microsoft Duplex я не думаю, что это сделает то, что вы хотите. Может быть какой-то другой умный способ сделать это с помощью Kung Fu WCF, но в моем случае я создал «PassThruService» для сервера, который реализовал тот же контракт, что и реальный сервис, и отправил любые запросы, полученные на клиент.

Это часть моего кода, которая объясняет суть этого.

private const int OPERATION_TIMEOUT = 5000;
private MyServiceClient m_client = new MyServiceClient();

public bool IsAlive() {
    try {
        logger.Debug("PassThruService IsAlive.");

        bool isAlive = false;
        ManualResetEvent isAliveMRE = new ManualResetEvent(false);

        m_client.IsAliveComplete += (s, a) => { isAlive = a.Result; isAliveMRE.Set(); };
        m_client.IsAliveAsync();

        if (isAliveMRE.WaitOne(OPERATION_TIMEOUT)) {
            return isAlive;
        }
        else {
            throw new TimeoutException();
        }
    }
    catch (Exception excp) {
        logger.Error("Exception PassThruService IsAlive. " + excp.Message);
        throw;
    }
...