簡體   English   中英

為引用的裝配創建單例

[英]Create a singleton for referenced assembly

我有一個可以通過SDK(項目中引用的.DLL文件)進行控制的硬件組件。 我正在嘗試實現一個幫助程序類,該類將處理對象的實例化並將所需的object reference給每個需要它的窗口。 這是我在窗口后面的代碼中創建對象的方式:

    //private fields
    SystemConnector myConn; 
    MyHardware mySystem; // this is the object i need a reference to

    public Window1()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        SystemDiscoverer SystemDiscoverer = new SystemDiscoverer();
        SystemDiscoverer.Discovered += (sysInfo) =>
        {
            myConn = new SystemConnector(sysInfo.IPAddress);

            if (myConn != null)
                mySystem = new MyHardware(myConn);

        };
        SystemDiscoverer.Discover();
    }

    private void WindowBase_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        if (myConn != null)
            myConn.Dispose();

        if (mySystem != null)
            mySystem.Dispose();
    }

我想將此邏輯移到幫助器類中,但是我有一些問題找不到解決方案:

  • 我能找到的所有Singleton示例都是針對自定義對象的,並且沒有解釋引用對象的用法。
  • 由於對象是在事件處理程序中完成的,因此該如何處理它的創建?

要處理來自事件處理程序的創建,請嘗試:

        LazyInitializer.EnsureInitialized(...)

它是線程安全的,因此您應該能夠為單例初始化靜態屬性就可以了。

MSDN文章在這里:

http://blogs.msdn.com/b/jolud/archive/2010/04/02/initialization-of-shared-resources.aspx

一個示例,來自ASP.NET MVC 4標准項目模板。

    public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute {
    private static SimpleMembershipInitializer _initializer;
    private static object _initializerLock = new object();
    private static bool _isInitialized;

    public override void OnActionExecuting(ActionExecutingContext filterContext) {
        // Ensure ASP.NET Simple Membership is initialized only once per app start
        LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
    }

    private class SimpleMembershipInitializer {
        public SimpleMembershipInitializer() {
            Database.SetInitializer<UsersContext>(null);

            try {
                using(var context = new UsersContext()) {
                    if(!context.Database.Exists()) {
                        // Create the SimpleMembership database without Entity Framework migration schema
                        ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                    }
                }

                WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
            }
            catch(Exception ex) {
                throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
            }
        }
    }
}

我將使用async方法將MyHardware類包裝在單例中,該方法包裝SystemDiscoverer.Discovered事件:

public sealed class MyHardwareSingleton
{
    static MyHardwareSingleton()
    { }

    private MyHardwareSingleton()
    { }

    private static readonly MyHardwareSingleton _myHardware = new MyHardwareSingleton();
    private SystemConnector _myConn;
    private MyHardware _mySystem;

    public MyHardwareSingleton Instance
    {
        get { return _myHardware; }
    }

    public Task<MyHardware> GetHardwareAsync()
    {
        if (_mySystem != null)
        {
            return Task.FromResult(_mySystem);
        }

        var tcs = new TaskCompletionSource<MyHardware>();

        SystemDiscoverer SystemDiscoverer = new SystemDiscoverer();

        SystemDiscoverer.Discovered += (sysInfo) =>
        {
            myConn = new SystemConnector(sysInfo.IPAddress);

            if (myConn != null)
            {
                mySystem = new MyHardware(myConn);
                tcs.TrySetResult(mySystem);
                return tcs.Task;
            }
            // This indicated that myConn came back null.
            tcs.TrySetResult(null);
            return tcs.Task;
        };
        // Make SystemDiscoverer run asynchrnously. We will await it so when it completes we will get the desired MyHardware instance.
        SystemDiscoverer.DiscoverAsync();
        return tcs.Task;
    }
}

DiscoverAsync可能會添加到SystemConnector類中,如下所示:

public Task DiscoverAsync()
{
   return Task.Run(() => Discover());
}

然后您可以通過以下代碼從代碼中調用它:

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
     var myHardware = await MyHardwareSingleton.Instance.DiscoverAsync();
}

當然,我沒有處理任何異常處理/取消。 這只是使用TAP可以完成的操作的一個示例

暫無
暫無

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

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