Signalr 不同集线器之间是否可以共享信号器组?

Signalr 不同集线器之间是否可以共享信号器组?,signalr,Signalr,在找到与组通信的方法后,似乎某个组的中心名称已被禁用。如果这是正确的(如果我错了,请让我知道),有没有办法让一个中心访问另一个中心的组,或者更好的办法是拥有某种全球组 我的问题是,我有一个中心将客户机添加到组中: public class GameService : Hub, IGameService ... public void CreateNewGame(CreateGameDto game) { game.Creator = UserRepo.GetUser(Co

在找到与组通信的方法后,似乎某个组的中心名称已被禁用。如果这是正确的(如果我错了,请让我知道),有没有办法让一个中心访问另一个中心的组,或者更好的办法是拥有某种全球组

我的问题是,我有一个中心将客户机添加到组中:

public class GameService : Hub, IGameService
...
public void CreateNewGame(CreateGameDto game)
    {
        game.Creator = UserRepo.GetUser(Context.ConnectionId);
        var newGame = GameRepo.CreateNewGame(game);
        Groups.Add(Context.ConnectionId, newGame.GameId.ToString(CultureInfo.InvariantCulture));
        Clients.Caller.JoinedGame(newGame);
    }
另一个中心完全需要向该群体广播:

    public class MessagingService : Hub , IMessageService
    ...
        public void AddMessage(MessageDto message)
    {
        message.User = UserRepo.GetUser(Context.ConnectionId);
        MessageRepo.AddMessage(message);
        Clients.Group(message.User.GameId.ToString(CultureInfo.InvariantCulture))
            .ReceivedMessage(message);
    }
到目前为止,客户端从未收到此广播

编辑以添加客户端代码。 这是客户端信号器设置,我创建了一个框架,允许我将服务接口与Castle动态代理一起使用,这样我就不会通过字符串名调用服务和方法

public abstract class BaseClientProxy<TServer,TClient>
{
    public  TServer ServiceProxy;

    protected BaseClientProxy(HubConnection conn)
    {
        ServiceProxy = CreateProxy(conn);
    }

    private ProxyGenerator _generator;
    protected IHubProxy Proxy;
    protected TClient Receiver;

    protected TServer CreateProxy(HubConnection conn)
    {
        Proxy = conn.CreateHubProxy<TServer>();

        _generator = new ProxyGenerator();

        return (TServer)_generator.CreateInterfaceProxyWithoutTarget(typeof(TServer), new HubProxyInterceptor(Proxy));
    }

    public void SetReceiver(TClient receiver)
    {
        Receiver = (TClient)_generator.CreateInterfaceProxyWithTarget(typeof(TClient), receiver);
        RegisterEvents();
    }

    protected void RegisterEvents()
    {
        Action<MethodInfo> regAction = RegisterEvent<object>;
        var methods =
            typeof (TClient).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
        foreach (var methodInfo in methods)
        {
            var locInfo = methodInfo;
            if (locInfo.GetParameters().Length > 0)
            {
                var regMethod = typeof(BaseClientProxy<TServer, TClient>).GetMethodExt(regAction.Method.Name, typeof(MethodInfo));
                var genAction = regMethod.MakeGenericMethod(locInfo.GetParameters()[0].ParameterType);
                genAction.Invoke(null, new object[] { locInfo });
            }
            else
            {
                Proxy.On(locInfo.Name, () =>locInfo.Invoke(Receiver, null));
            }
        }
    }

    protected void RegisterEvent<TDto>(MethodInfo method)
    {
        Proxy.On<TDto>(method.Name, x => method.Invoke(Receiver, new object[] {x}));
    }
}

public class HubProxyInterceptor : IInterceptor
{
    protected IHubProxy Proxy;

    public HubProxyInterceptor(IHubProxy proxy) 
    {
        Proxy = proxy;
    }

    protected async void Invoke<TDto>(string methodName, TDto dto)
    {
        await Proxy.Invoke(methodName, dto);
    }

    protected async void Invoke(string methodName)
    {
        await Proxy.Invoke(methodName);
    }

    public void Intercept(IInvocation invocation)
    {
        if (invocation.Arguments.Length > 0)
        {
            Invoke(invocation.Method.Name, invocation.Arguments[0]);
        }
        else
        {
            Invoke(invocation.Method.Name);
        }
    }
}
公共抽象类BaseClientProxy
{
公共TServer服务代理;
受保护的BaseClientProxy(HUB连接连接)
{
ServiceProxy=CreateProxy(conn);
}
专用ProxyGenerator\u生成器;
受保护的ihubbroxy代理;
受保护的TClient接收器;
受保护的TServer CreateProxy(HUB连接连接)
{
Proxy=conn.CreateHubProxy();
_生成器=新的代理生成器();
return(TServer)u generator.CreateInterfaceProxyWithoutTarget(typeof(TServer),新的HubProxyInterceptor(Proxy));
}
公共无效设置接收器(TClient接收器)
{
Receiver=(TClient)\u generator.CreateInterfaceProxyWithTarget(类型为(TClient),Receiver);
RegisterEvents();
}
受保护的无效注册表事件()
{
Action Regation=RegisterEvent;
var方法=
typeof(TClient).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
foreach(方法中的var methodInfo)
{
var locInfo=methodInfo;
如果(locInfo.GetParameters().Length>0)
{
var regMethod=typeof(BaseClientProxy).GetMethodExt(regAction.Method.Name,typeof(MethodInfo));
var genAction=regMethod.MakeGenericMethod(locInfo.GetParameters()[0].ParameterType);
Invoke(null,新对象[]{locInfo});
}
其他的
{
On(locInfo.Name,()=>locInfo.Invoke(Receiver,null));
}
}
}
受保护的无效RegisterEvent(MethodInfo方法)
{
On(method.Name,x=>method.Invoke(Receiver,newobject[]{x}));
}
}
公共类HubProxyInterceptor:IInterceptor
{
受保护的ihubbroxy代理;
公共HubProxyInterceptor(IHubProxy代理)
{
代理=代理;
}
受保护的异步void调用(string methodName,TDto dto)
{
等待Proxy.Invoke(methodName,dto);
}
受保护的异步void调用(string methodName)
{
等待Proxy.Invoke(methodName);
}
公共无效拦截(IInvocation调用)
{
if(invocation.Arguments.Length>0)
{
调用(invocation.Method.Name,invocation.Arguments[0]);
}
其他的
{
调用(invocation.Method.Name);
}
}
}
这些代码段来自一个singleton类,该类在windsor容器中建立连接并注册服务

private SignalRManager()
    {
        var settings = Settings.GetSettings<IClientSettings>(ConfigurationManager.AppSettings);

        Connection = new HubConnection(settings.SignalRServerUri);

        ioc = new WindsorContainer();
        ioc.Register(
            Component.For<BaseClientProxy<IUserService, IUserClient>>().Instance(new UserServiceProxy(Connection)),
            Component.For<BaseClientProxy<IDrawingService, IDrawingClient>>().Instance(new DrawingServiceProxy(Connection)),
            Component.For<BaseClientProxy<IMessageService, IMessageClient>>().Instance(new MessageServiceProxy(Connection)),
            Component.For<BaseClientProxy<IScoreBoardService, IScoreBoardClient>>().Instance(new ScoreBoardServiceProxy(Connection)),
            Component.For< BaseClientProxy<IGameService,IGameClient>>().Instance(new GameServiceProxy(Connection)));
        Connection.Start().Wait();
    }
   public TClient GetService<TClient,TReceiver>(TReceiver receiver) where TClient : IService
    {
        var proxy = ioc.Resolve<BaseClientProxy<TClient, TReceiver>>();
        proxy.SetReceiver(receiver);
        return proxy.ServiceProxy;
    }
专用信号管理器()
{
var settings=settings.GetSettings(ConfigurationManager.AppSettings);
连接=新的HUB连接(settings.signalserverURI);
ioc=新WindsorContainer();
国际奥委会,登记(
Component.For().Instance(新的UserServiceProxy(连接)),
Component.For().Instance(新的DrawingServiceProxy(连接)),
Component.For().Instance(新MessageServiceProxy(连接)),
Component.For().Instance(新的ScoreBoardServiceProxy(连接)),
组件。用于()。实例(新的GameServiceProxy(连接));
Connection.Start().Wait();
}
公共TClient GetService(TReceiver receiver),其中TClient:IService
{
var proxy=ioc.Resolve();
代理。设置接收方(接收方);
返回proxy.ServiceProxy;
}
在此代码中,HubProxyInterceptor负责对服务器进行所有调用

BaseClientProxy中的RegisterEvents方法负责连接从服务器到客户端的调用。TServer和TClient类型参数是两个不同但相似的接口,TServer将由服务器端的Hub类实现,TClient由调用SetReceiver时传入的我的WPF视图模型实现。

您可以在MessagingService.AddMessage中使用,将消息发送到另一个Hub的组

public void AddMessage(MessageDto message)
{
IHubContext gameContext=GlobalHost.ConnectionManager.GetHubContext();
message.User=UserRepo.GetUser(Context.ConnectionId);
MessageRepo.AddMessage(message);
gameContext.Clients.Group(message.User.GameId.ToString(CultureInfo.InvariantCulture))
.收到的信息(信息);
}

如果您不想在每次调用AddMessage时重新创建
gameContext
,您可以将它存储在一个字段中。

这也不起作用,我使用的是自主机配置吗?服务器是一个控制台应用程序,我现在唯一的客户端是WPF应用程序。好的,在GameService中,我尝试拉出MessageService上下文并添加到组中,结果成功了,这很好,但这只是意味着我也需要对其他服务执行相同的操作,这将比我只使用GameService上下文更需要代码。你有没有想过为什么它是以一种方式工作的,而不是以另一种方式工作的?我必须看看你的客户端代码。显然,我的建议应该有效。当您启动Signal连接时,可能您的客户端没有正确订阅GameService集线器。我添加了客户端代码,用于处理连接到集线器的连接,希望这是清楚的。