[英]How do I create Singleton instance for a library referenced from nuget
[英]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();
}
我想將此邏輯移到幫助器類中,但是我有一些問題找不到解決方案:
要處理來自事件處理程序的創建,請嘗試:
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.