2

我有一个信号器客户,我想成为全球性的。

我认为在端点配置的 Init() 中创建信号器客户端是最好的。

public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
    public static HubConnection hubConnection;
    public static IHubProxy hubProxy;

    public void Init()
    {
        Configure.With()
            .DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains(".Events."))
            .DefiningMessagesAs(t => t.Namespace != null && t.Namespace.Contains(".Messages."))
            .StructureMapBuilder(new Container(new DependencyRegistry()));

        Configure.Serialization.Json();

        hubConnection = new HubConnection("http://localhost:58120"); 
        hubProxy = hubConnection.CreateHubProxy("AmsHub");
        hubProxy.On<string>("receiveServerPush", x => System.Diagnostics.Debug.WriteLine(x));
        hubConnection.Start().Wait();
    }

    public class DependencyRegistry : Registry
    {
        public DependencyRegistry()
        {
            Scan(x =>
            {
                x.AssembliesFromApplicationBaseDirectory();
                x.ExcludeNamespace("StructureMap");
                x.WithDefaultConventions();
            });
        }
    }
}

我感到困惑的是,我应该如何在消息处理程序中引用 hubConnection 和 hubProxy?我好像在偷工减料地操纵 NServicebus。

public class TestHandler : IHandleMessages<AMS.Infrastructure.Events.IEvent>
{
    public void Handle(AMS.Infrastructure.Events.IEvent message)
    {
        EndpointConfig.hubProxy.Invoke("ServerFunction", "yodle");
    }
}

PS:我需要连接和代理是全球性的原因是因为根据信号员的说法,产生一个新的 hubConnection 是昂贵的。他们强烈反对一遍又一遍地创建和破坏集线器连接。他们发现使集线器连接全局/静态(?)没问题。

4

2 回答 2

6

在这种情况下,您的集线器连接/代理确实与 EndPointConfiguration 类无关。它们不使用也不需要这种类型的任何数据才能发挥作用。

我建议将它们放在自己的惰性初始化单例中,并在首次访问时自动启动它们。这看起来像:

public class Hub
{
    private static Lazy<Hub> instance = new Lazy<Hub>(() => new Hub());

    public static Hub Instance { get { return instance.Value; } }

    private Hub()
    {
        this.Connection = new HubConnection("http://localhost:58120"); 
        this.Proxy = Connection.CreateHubProxy("AmsHub");
        this.Proxy.On<string>("receiveServerPush", x => System.Diagnostics.Debug.WriteLine(x));
        this.Connection.Start().Wait(); 
    }

    public HubConnection Connection { get; private set; }
    public IHubProxy Proxy { get; private set; }
}

然后,您的消费者只需使用:

public class TestHandler : IHandleMessages<AMS.Infrastructure.Events.IEvent>
{
    public void Handle(AMS.Infrastructure.Events.IEvent message)
    {
        Hub.Instance.Proxy.Invoke("ServerFunction", "yodle");
    }
}

这样做的好处是在第一次使用之前不创建和启动,并将这种类型隔离到它自己的类中。

鉴于您还在内部处理订阅,您还可以选择封装您的方法以简化使用:

public class Hub
{
    private static Lazy<Hub> instance = new Lazy<Hub>(() => new Hub());

    public static Hub Instance { get { return instance.Value; } }

    private Hub()
    {
        this.Connection = new HubConnection("http://localhost:58120"); 
        this.Proxy = Connection.CreateHubProxy("AmsHub");
        this.Proxy.On<string>("receiveServerPush", x => System.Diagnostics.Debug.WriteLine(x));
        this.Connection.Start().Wait(); 
    }

    private HubConnection Connection { get; set; }
    private IHubProxy Proxy { get; set; }

            public static Task Invoke(string method, params Object[] args)
            {
                 return Instance.Proxy.Invoke(method, args);
            }

            public static Task<T> Invoke<T>(string method, params Object[] args)
            {
                 return Instance.Proxy.Invoke<T>(method, args);
            }
}

有了以上内容,您可以使用:Hub.Invoke("ServerFunction", "yodle");

于 2013-08-16T22:09:31.917 回答
0

@reed-copsey 旧帖,但感谢您的回复,它对我帮助很大。

在我的例子中,我正在创建一个 Azure 函数,它将连接到作为 ASP.NET MVC 站点的一部分的 SignalR 集线器。在发送通知之前,我需要确保连接安全/经过身份验证。

所以我的示例包括验证和获取 cookie。

public class Hub
    {
        private static readonly string HOMEPAGE = ConfigurationManager.AppSettings["Homepage"];
        private static readonly string NOTIFICATION_USER = ConfigurationManager.AppSettings["NotificationUser"];
        private static readonly string NOTIFICATION_PASSWORD = ConfigurationManager.AppSettings["NotificationPassword"];

        private static Lazy<Hub> instance = new Lazy<Hub>(() => new Hub());
        public static Hub Instance { get { return instance.Value; } }

        private Hub()
        {
            ClientHandler = new HttpClientHandler();
            ClientHandler.CookieContainer = new CookieContainer();
            using (Client = new HttpClient(ClientHandler))
            {
                var content = string.Format("Email={0}&Password={1}", NOTIFICATION_USER, NOTIFICATION_PASSWORD);
                var response = this.Client.PostAsync(HOMEPAGE + "/Account/Login", new StringContent(content, Encoding.UTF8, "application/x-www-form-urlencoded")).Result;
            }
            Connection = new HubConnection($"{HOMEPAGE}/");
            Connection.CookieContainer = ClientHandler.CookieContainer;
            Proxy = Connection.CreateHubProxy("notificationsHub");
            //this.Proxy.On<string>("receiveServerPush", x => System.Diagnostics.Debug.WriteLine(x));
            Connection.Start().Wait();
        }

        public HttpClientHandler ClientHandler { get; private set; }
        public HttpClient Client { get; private set; }
        public HubConnection Connection { get; private set; }
        public IHubProxy Proxy { get; private set; }

        public static Task Invoke(string method, params Object[] args)
        {
            return Instance.Proxy.Invoke(method, args);
        }

        public static Task<T> Invoke<T>(string method, params Object[] args)
        {
            return Instance.Proxy.Invoke<T>(method, args);
        }

    }
于 2022-02-17T13:34:37.577 回答