C# 为引用的程序集创建单例

C# 为引用的程序集创建单例,c#,dll,singleton,C#,Dll,Singleton,我有一个可以通过SDK控制的硬件组件(项目中引用的.DLL文件)。 我正在尝试实现一个帮助器类,该类将处理对象的实例化,并为每个需要它的窗口提供所需的对象引用。 这是我在窗口的代码隐藏中创建对象的方式: //private fields SystemConnector myConn; MyHardware mySystem; // this is the object i need a reference to public Window1() {

我有一个可以通过SDK控制的硬件组件(项目中引用的
.DLL
文件)。 我正在尝试实现一个帮助器类,该类将处理对象的实例化,并为每个需要它的窗口提供所需的
对象引用。
这是我在窗口的代码隐藏中创建对象的方式:

    //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();
    }
我想将此逻辑移到helper类中,但我有一些问题找不到解决方案:

  • 我能找到的所有单例示例都是针对自定义对象的 并且没有解释引用对象的用法
  • 如何处理 对象的创建,因为它是在事件处理程序中完成的
要从事件处理程序处理创建,请尝试:

        LazyInitializer.EnsureInitialized(...)
它是线程安全的,所以您应该能够很好地初始化单例的静态属性

MSDN文章如下:

例如,来自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);
            }
        }
    }
}
公共密封类初始化SimpleMembershipAttribute:ActionFilterAttribute{
私有静态SimpleMembershipInitializer\u initializer;
私有静态对象_initializerLock=新对象();
私有静态布尔值初始化;
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext){
//确保每次应用程序启动仅初始化一次ASP.NET简单成员身份
LazyInitializer.确保重新初始化(参考初始值设定项,参考初始值设定项,参考初始值设定项锁定);
}
私有类SimpleMembershipInitializer{
公共SimpleMembershipInitializer(){
Database.SetInitializer(null);
试一试{
使用(var context=new UsersContext()){
如果(!context.Database.Exists()){
//创建没有实体框架迁移模式的SimpleMembership数据库
((IObjectContextAdapter)context.ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection(“DefaultConnection”、“UserProfile”、“UserId”、“UserName”,autoCreateTables:true);
}
捕获(例外情况除外){
抛出新的InvalidOperationException(“无法初始化ASP.NET简单成员身份数据库。有关详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=256588“,ex);
}
}
}
}

我将使用一个
异步
方法将
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;
    }
}
然后您可以通过以下方式从代码中调用它:

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

当然,我没有处理任何异常处理/取消。这只是一个例子,说明了如何使用事件
SystemDiscoverer.Discovered
在调用
SystemDiscoverer.Discover()
?@YuvalItzchakov是的,它看起来很有希望,但我对
async
方法不太熟悉,所以我还不确定是否要使用它……我建议您研究一下。您可以从阅读Stephan Clearys的博客开始:我向您保证,它将为您节省大量样板代码。
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
     var myHardware = await MyHardwareSingleton.Instance.DiscoverAsync();
}