Как я могу перезвонить клиенту и выставить новый канал с контекстом экземпляра
Я делаю 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 и обработать все самому?
1 ответ
Вы не можете передать контекст экземпляра в качестве параметра в любой контракт операции. Это не имеет смысла, потому что этот контекст имеет локальную область видимости. Он называется "контекст экземпляра" = это контекст текущего экземпляра службы. В дуплексном сценарии и клиент, и сервер имеют собственный сервис:
- Клиенты вызывают сервис сервера через его прокси
- Сервер вызывает сервис клиента через полученный канал обратного вызова
Контекст экземпляра службы сервера имеет значение только на сервере. Не ясно, чего вы пытаетесь достичь (кроме очень сложной архитектуры).
- Если вы хотите поделиться контекстом на клиенте, вы можете попытаться передать контекст экземпляра, использованный для самого первого созданного вами прокси - я не уверен, что он будет работать, но вы можете попробовать его
- Если вы хотите разделить контекст экземпляра сервиса между несколькими прокси, вы должны разработать свой собственный
IInstanceContextProvider
и, возможно, также свой собственныйIInstanceProvider
(в зависимости от того, чего вы хотите достичь), оберните их в поведение и добавьте их в сервис. Это поставит под контроль всю сложность обработки сеанса и правильного освобождения экземпляра (очевидно, у него есть свои плюсы и минусы).
Но действительно ли это нужно? Когда я смотрю на ваш код, я вижу, что одного сервиса и одного прокси достаточно. Также ваш JoinRoom
Операция вообще не нуждается в обратном вызове, это может быть просто метод ответа на запрос.