2015-04-11 1 views
0

У меня есть два концентратора, который используется для отслеживания пользователей (chatHub) и другого концентратора, который используется для панели управления (dashHub).Вызов одного концентратора из другого концентратора с правильным контекстом в SignalR

Когда новый пользователь подключается к веб-сайту, он вызывает метод Server.Connect, который отслеживает идентификаторы и группы пользователей. Затем я хочу позвонить DashHub.Update() из ChatHub, чтобы все подписчики тире получали новые данные.

I have read this on the official documentation и понять, что там происходит, но я действительно хочу назвать метод DashHub.Update(), в котором есть некоторая логика, а не просто отправлять сообщение через контекст. Оглядываясь на Stackoverflow и другие примеры, я дошел до этого, рабочего решения, но это просто не выглядит правильным.

ChatHub.cs - UpdateDashboardClients() вызывается каждый раз, когда мне нужно нажимать данные на приборную панель. Это личное.

private void UpdateDashboardClients() 
{ 
     DashHub dh = new DashHub(); 
     dh.SendNew(); 
} 

DashHub.cs - Это прекрасно работает на стороне клиента dashbpaord и мое решение, чтобы исправить Context == null проблемы при вызове извне Hub, с другой хаб я использовал это.

public void SendNew() 
{ 
    if (Context == null) 
    { 
     IHubContext contextDashHub = GlobalHost.ConnectionManager.GetHubContext<DashHub>(); 
     contextDashHub.Clients.Clients(<clients>).PushNew(<data>) 
    } 
    else 
    { 
     Clients.Clients(<clients>).PushNew(<data>); 
    } 

} 

Я попытался установить разрешенный IHubContext contextDashHub к this.Context с броском, но это не удается, потому что this.Context имеет типа HubCallerContext.

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

Я прочитал что-то о Proxies на сервере, но не знаю, как это работает, и если это даже правильный путь.

Это «обходное решение» работает для меня сейчас, но оно не очень многократно используется и повторяет код, что делает его очень вонючим.

Я полагаю, что мне нужно как-то использовать DI из ChatHub (аналогично получению контекста), чтобы сделать это правильно, но я также довольно новичок в DI и не знаю точно, как это сделать.

Не могли бы вы предоставить правильный способ сделать это.

ответ

1

Как вы уже заметили, то, что вы пытаетесь сделать, это не правильный подход. Тот факт, что вы действительно хотите создать экземпляр концентратора самостоятельно и вызвать метод на нем, неверен. Жизненный цикл экземпляров хаба должен быть оставлен под контролем среды выполнения SignalR.

Тот факт, что вы получаете пустой контекст, совершенно логичен, и вы не должны пытаться его изменить, это не имеет смысла в противном случае. Например, если в вашем концентраторе есть код, который проверяет конечную точку Caller, это не может работать даже с логической точки зрения (в этом случае нет вызывающего абонента). Вы никогда не должны пытаться так взломать, потому что вы не можете построить контекст, который будет работать для каждого случая.

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

DI может помочь вам в чистке такого кода, но это не обязательно. Это также зависит от размера вашего приложения, но если это всего лишь куча типов, вы можете воспользоваться некоторыми ярлыками и по-прежнему держать код под контролем. В противном случае, поддержка DI от SignalR не сложна в управлении, читайте об этом, и вы обнаружите, что это довольно легко. Если вы поедете с DI, вы можете получить, что ваши хабы получают экземпляр службы широковещания (всегда один и тот же экземпляр или всегда новый? Он может работать в обоих направлениях, он зависит от того, как он реализован) и соответственно использовать его в своих методах, передавая в правильных контекстах для каждого случая.

+0

Спасибо. Я понимаю, почему нет контекстов и всего параллелизма SingnalR, это действительно потрясающе. Полагаю, мне нужно создать отдельный бизнес-класс, который разрешает HubContext и вызывает динамический метод, не входя в код концентратора. Просто, если я или кто-то изменяет подпись метода-концентратора, бизнес-уровень Динамический вызов концентратора завершится с ошибкой и, возможно, без ошибок. Причины, по которым я хочу создать экземпляр концентратора, - это явно убедиться, что метод, который я вызываю, существует, и он не будет запускаться. Как бы я тогда набирал строго типизированные вызовы хаба из разрешенного HubContext? – ppumkin

+1

Интерфейс вашего сервиса фактически обеспечит эту систему безопасности. Сервисные методы имеют строго типизированную подпись, поэтому любой, кто бы назвал ее, не имел бы проблемы, которую вы описываете. Вместо вызова строго типизированного метода Hub, который является взломом, потому что вы должны его создать, и мы увидели, что это плохо, вы вызываете службу, которая строго типизирована и безопасна для звонков без того, что вызывающие абоненты рискуют от динамических вызовов. Итак, это в основном та же идея, что и вы, но сделанная на чем-то, что вы можете создать безопасно и чисто. – Wasp

+0

Да, интерфейсы на сервисном классе имеют смысл. Мне просто нужен был маленький намек. Не было очевидным, когда смотрел на новый код целую вечность. благодаря – ppumkin