为引用的程序集创建一个单例

本文关键字:一个 单例 引用 程序集 创建 | 更新日期: 2023-09-27 18:03:10

我有一个可以通过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();
    }

我想把这个逻辑移动到一个助手类,但我有一些问题,我找不到一个解决方案:

    我能找到的所有单例示例都是针对自定义对象的也没有解释引用对象的用法。
  • 如何处理对象的创建,因为它是在事件处理程序内部完成的?

为引用的程序集创建一个单例

要处理事件处理程序的创建,请尝试:

        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);
            }
        }
    }
}

我会将MyHardware类包装在单例中,并使用async方法包装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

可以完成的示例