我有一个使用SignalR用C#编写的工作Web服务器。它是一个自我托管的Owin应用程序。一切正常。
现在我必须在不同的AppDomain中重新定位我的控制器。这打破了SignalR部分,因为GlobalHost
仅在一个AppDomain中保持不变,并且不可序列化(因此我无法将其原样传递给其他AppDomain)。
我发现了许多关于从Controller /其他类/其他类调用SignalR hubs方法的示例/问题/教程,但没有从Default AppDomain(Owin应用程序初始化的那个)之外的任何内容中找到。
如何从与集线器不同的AppDomain中设置的控制器向客户端发送消息?
答案 0 :(得分:0)
从外面看:
var context = GlobalHost.ConnectionManager.GetHubContext<YOURHUBCLASS>();
context.Clients.All.yourHubTask();
答案 1 :(得分:0)
我发现的解决方案非常简单:对于任何app -main间通信,我们需要能够跨越AppDomain边界的东西,即数据或类的代理。
因此,以下工作:
创建一个扩展MarshalByRefObject的类:当我们将它传递给另一个AppDomain中的其他类时,这将自动为该类创建一个代理
public class InterAppDomainForSignalR : MarshalByRefObject
{
public void Publish(PublishParameter param) {
var clients = GlobalHost.ConnectionManager.GetHubContext<TradeHub>().Clients;
dynamic chan;
if (param.group != null && param.group.Length > 0)
{
chan = clients.Group(param.group, param.ids);
}
else
{
if(param.ids == null || param.ids.length = 0) {
return; //not supposed to happen
}
chan = clients.Client(param.ids[0]);
}
chan.OnEvent(param.channelEvent.ChannelName, param.channelEvent);
}
}
[Serializable]
public class PublishParameter
{
public string group { get; set; }
public string[] ids { get; set; }
public ChannelEvent channelEvent { get; set; }
}
确保您的参数为Serializable
:此处,PublishParameter
显然是正确的,但ChannelEvent
也必须是可序列化的,并且只包含Serializable
个成员等。
创建此类的实例并将其传递给不同AppDomains中的对象(communicationChannel
是InterAppDomainForSignalR
的实例):
AppDomain domain = AppDomain.CreateDomain(myDomainName);
Type type = typeof(ClassInOtherAppDomain);
ClassInOtherAppDomain startpoint = (ClassInOtherAppDomain)domain.CreateInstanceAndUnwrap(
type.Assembly.FullName,
type.FullName) as ClassInOtherAppDomain;
var session = startpoint.initialize(communicationChannel);
将communicationChannel
存储在ClassInOtherAppDomain
实例中,并随意使用;):
public class ClassInOtherAppDomain {
private InterAppDomainForSignalR communicationChannel { get; set; }
public void initialize(InterAppDomainForSignalR communicationChannel) {
this.communicationChannel = communicationChannel;
}
public void Publish(PublishParameter param) {
this.communicationChannel.Publish(param);
}
}
就是这样=)