Как я могу перезвонить клиенту и открыть новый канал с контекстом экземпляра

Я создаю службу WCF с netTcpBinding, в которой есть главное лобби с несколькими чатами, в которые могут войти клиенты. Класс Lobby реализует ILobby как сервисный контракт.

Когда клиент хочет войти в комнату, я хочу перезвонить клиенту, открывающему новый канал, содержащий InstanceContext для комнаты, в которую он только что вошел, но после долгих поисков я сомневаюсь, что это возможно.

Например, на стороне службы у меня может быть

class Lobby : ILobby
{
    Dictionary<string, Chatroom> rooms;

    public void JoinRoom(string roomname)
    {
        if (rooms[roomname].TryEnter()) {}
    }
}

class ChatRoom : IChatRoom
{
    public bool TryEnter(string username)
    {
        ILobbyCallback callback =
            OperationContext.Current.GetCallbackChannel<ILobbyCallback>();
        // How do I do this next bit?
        callback.JoinedRoom(pass some instance context here);
        return true;
    }
}

В методе обратного вызова на стороне клиента я хочу

public void JoinedRoom(InstanceContext for the room on the service side)
{
    // Create a new WCF proxy using above InstanceContext
    // Create a WPF UI for the new room passing the proxy so it can communicate
    // with the room class directly without going via the root service
}

Это возможно? Как лучше всего создавать новые классы с собственными контрактами на стороне службы? Или мне просто нужно объединить все в один массивный класс MyService и обрабатывать все самому?


person Freddy Flares    schedule 15.09.2011    source источник


Ответы (1)


Вы не можете передать контекст экземпляра в качестве параметра любому контракту операции. Это не имеет смысла, потому что этот контекст имеет локальную область действия. Это называется «контекст экземпляра» = это контекст текущего экземпляра службы. В дуплексном сценарии и клиент, и сервер имеют свою собственную службу:

  • Клиенты вызывают сервис сервера через его прокси
  • Сервер вызывает службу клиента через полученный канал обратного вызова

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

  • Если вы хотите поделиться контекстом на клиенте, вы можете попытаться передать контекст экземпляра, используемый для самого первого созданного вами прокси - я не уверен, что это сработает, но вы можете попробовать.
  • Если вы хотите разделить контекст экземпляра службы между несколькими прокси-серверами, вы должны разработать свои собственные IInstanceContextProvider и, возможно, также свои собственные IInstanceProvider (в зависимости от того, чего вы хотите достичь), обернуть их поведением и добавить в службу. Это поставит под ваш контроль всю сложность обработки сеанса и правильного выпуска экземпляра (очевидно, у этого есть свои плюсы и минусы).

Но так ли это необходимо? Когда я смотрю на ваш код, я вижу, что достаточно одного сервиса и одного прокси. Также ваша операция JoinRoom вообще не должна использовать обратный вызов, это может быть просто метод ответа на запрос.

person Ladislav Mrnka    schedule 15.09.2011