我有一项服务,希望通过SignalR(在OWIN上)添加与之交互的能力。有很多关于如何向客户端发送消息的示例,但是如何从客户端接收消息并将其转发给父服务?
e.g。
public class MyService
{
...
public void LaunchSR()
{
_srWebApp = WebApplication.Start<SrStartup>("http://localhost:" + _signalRPortNumber.ToString());
_srContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
}
public class SrStartup
{
public void Configuration(Owin.IAppBuilder app)
{
app.MapConnection("/raw", typeof(PersistentConnection), new ConnectionConfiguration { EnableCrossDomain = true });
app.MapHubs();
}
}
public class MyHub : Hub
{
public void SendToServer(string data)
{
//!! Don't have a reference to MyService instance,
//!! so LocalCommand is out of scope
LocalCommand(data, null);
}
}
public void LocalCommand(data)
{
// Do Stuff in the main service context, accessing private objects etc.
}
}
SendToServer()
内的代码有编译时错误:
“无法通过嵌套类型MyHub访问外部类型MyService的非静态成员”。
我理解为什么会这样,但不知道如何正确地做到这一点。
答案 0 :(得分:2)
中心instances are transient,因此您需要创建某种反转。一种方法是在单例类中创建类似通信代理的东西,两者通过它进行通信。
public class HubToServiceProxy {
public static readonly HubToServiceProxy Instance = new HubToServiceProxy();
private HubToServiceProxy() {}
private MyService m_svc;
// call this when the service starts up, from the service
public void RegisterService (MyService svc) {
// Be very careful of multithreading here,
// the Proxy should probably lock m_svc on
// every read/write to ensure you don't have problems.
m_svc = svc;
}
// call this from the hub instance to send a message to the service
public void SendCommandToService(string data) {
m_svc.LocalCommand(data, null);
}
}
然后执行:
public class MyService
{
...
public MyService() {
HubToServiceProxy.Instance.RegisterService(this);
}
...
}
public class MyHub : Hub
{
public void SendToServer(string data)
{
HubToServiceProxy.Instance.SendCommandToService(data);
}
}
需要注意几点:
RegisterService (MyService svc)
可以完全删除并替换为要监听的事件:即您可以通过事件(或as close as .NET does it)实现Observer模式:而不是在通信代理中记录服务引用。
SendCommandToService
方法会引发CommandFromClient
事件而不是调用服务。 RegisterService (MyService svc)
应该是RegisterService (ILocalCommand svc)
,其中ILocalCommand
是定义LocalCommand
方法签名的接口,由MyService
实现有多种方法可以减少这种情况,您需要根据具体情况选择最佳方法。要记住的主要事情是集线器是瞬态的,因此它们必须调用某种非瞬态服务器端端点,它将:将消息传递给服务;或者返回一个对象实例,集线器可以传递消息以进行分发。显然,这个初始调用不能是另一个类的实例,所以静态或单例类是你唯一的选择。
相反,这是GlobalHost.ConnectionManager.GetHubContext<MyHub>()
方法允许server classes to communicate with clients实例的操作。它为您自己的实例提供非瞬态端点,以便在他们想要与客户端通信时进行调用。