簡體   English   中英

使用Autofac將類的Singleton實例注入SignalR Hub

[英]Injecting Singleton Instance of class into SignalR Hub using Autofac

我正在創建一個使用SignalR將實時推文廣播到地圖的應用程序。 我正在使用C#Tweetinvi庫( tweetinvi.codeplex.com )處理與連接到Twitter Streaming API相關的所有邏輯。

Twitter API指定任何時間都只能向Twitter打開一個流連接。 當我使用SignalR時,流連接和Hub類之間存在依賴關系。 我知道Hub類是臨時的,這意味着它在每次客戶端請求時都會創建,因此我需要確保注入到Hub類中的Twitter Stream類的實例是單例的,或者至少僅創建IFilteredStream在應用程序的生命周期中一次。 這是連接到API的樣板代碼:

public class TweetStream
    {
        private IFilteredStream _stream;
        public TweetStream()
        {
            var consumerKey = ConfigurationManager.AppSettings.Get("twitter:ConsumerKey");
            var consumerSecret = ConfigurationManager.AppSettings.Get("twitter:ConsumerSecret");

            var accessKey = ConfigurationManager.AppSettings.Get("twitter:AccessKey");
            var accessToken = ConfigurationManager.AppSettings.Get("twitter:AccessToken");

            TwitterCredentials.SetCredentials(accessKey, accessToken, consumerKey, consumerSecret);

            _stream = Stream.CreateFilteredStream();

        }
        // Return singular instance of _stream to Hub class for usage.
        public IFilteredStream Instance
        {
            get { return _stream; }
        }

    }

IFilteredStream接口公開如下所示的lambda方法,該方法允許實時接收Tweets,我希望能夠從我的SignalR Hub類中進行訪問:

_stream.MatchingTweetReceived += (sender, args) => {
        Clients.All.broadcast(args.Tweet);
};

這種方法的來源可以在這里找到

我已經嘗試實現Autofac,並且似乎已經建立了與Twitter API的連接,但是什么也沒有發生。 我已經嘗試調試此方案,但是不確定如何使用依賴項注入來調試這種情況。 我的Hub類當前如下所示:

public class TwitterHub : Hub
{
    private readonly ILifetimeScope _scope;
    private readonly TweetStream _stream;

    // Inject lifetime scope and resolve reference to TweetStream
    public TwitterHub(ILifetimeScope scope)
    {
        _scope = scope.BeginLifetimeScope();

        _stream = scope.Resolve<TweetStream>();

        var i = _stream.Instance;

        _stream.MatchingTweetReceived += (sender, args) => {
            Clients.All.broadcast(args.Tweet);
        };

        i.StartStreamMatchingAllConditions();
    }
}

最后,我的OWIN Startup類,在其中使用Autofac注冊依賴項和Hub:

[assembly: OwinStartup(typeof(TwitterMap2015.App_Start.OwinStartup))]

namespace TwitterMap2015.App_Start
{
    public class OwinStartup
    {
        public void Configuration(IAppBuilder app)
        {
            var builder = new ContainerBuilder();

            // use hubconfig, not globalhost
            var hubConfig = new HubConfiguration {EnableDetailedErrors = true};

            builder.RegisterHubs(Assembly.GetExecutingAssembly()); // register all SignalR hubs

            builder.Register(i => new TweetStream()).SingleInstance(); // is this the correct way of injecting a singleton instance of TweetStream?

            var container = builder.Build();

            hubConfig.Resolver = new AutofacDependencyResolver(container);

            app.MapSignalR("/signalr", hubConfig);
        }
    }
}

抱歉,如果這個問題有點混亂,我很難理解要實現此功能需要實現哪種架構! 可以就如何改進或應該如何改進提出建議/建議!

IMO不能正常工作,因為您正在連接事件以在特定的集線器實例的上下文上進行調用,而不管與Autofac有關的任何代碼(可能也有問題,但我不是這方面的專家)。 每當發生新連接或從客戶端調用方法時,都會調用集線器的構造函數。

  • 您每個客戶可能多次訂閱該事件。 我不知道您使用的是Twitter API,但是請注意,您在所有這些時間都調用i.StartStreamMatchingAllConditions()的事實對我來說似乎是錯誤的
  • 每次您在事件處理程序中為該實例的Clients成員創建一個關閉時,該關閉都應該在集線器被銷毀后消失(所以很可能您正在泄漏內存)

考慮到您正在通過Client.All進行呼叫,因此您需要做的是,這是獨立於任何特定呼叫者的純廣播,它是:

  • 在您的TwitterStream服務的構造函數中初始化您的Twitter連接
  • 在同一個地方(也許有一些間接,但可能沒有必要)以您TwitterHub中心上下文的實例TwitterHub
  • 訂閱事件並使用您剛剛獲取的上下文在事件上廣播

這樣的構造函數可能如下所示:

public service TwitterStream : ??? <- an interface here?
{
    ...

    public TwitterStream (ILifetimeScope scope ??? <- IMO you don't need this...)
    {
        //Autofac/Twitter stuff
        ...

        var context = GlobalHost.DependencyResolver.GetHubContext<TwitterHub>();

        _stream.MatchingTweetReceived += (sender, args) => {
            context.Clients.All.broadcast(args.Tweet);
        };

        //maybe more Autofac/Twitter stuff
        ...
    }

    ...
}

TwitterHub必須存在,但是如果您只需要它對所有人進行這種廣播,而無需監視連接或處理客戶端生成的呼叫的特殊代碼,則它可以為空,並且與您的實際集線器相關也可以代碼位於其外部,並使用IHubContext廣播消息。 這樣的代碼將在每次發推文時處理所有現有的已連接客戶端,因此無需跟蹤它們。

當然,如果您對分別處理客戶有更多要求,那么情況可能會有所不同,但是您的代碼並沒有使我反感。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM