为 DI 容器创建线程安全的单例包装器
我为 Ninject DI 容器创建了一个包装器,打算在 WPF 应用程序中使用它。我希望它是线程安全的,以防我需要在单独的线程中打开新窗口,但我对使用 volatile 关键字和锁定感到困惑。据我所知,锁定非常容易理解,但我不支持使用 volatile 关键字。从我的谷歌搜索结果中,我了解到 volatile 关键字确保多线程环境中指定实例的安全读取访问,但在更改指定实例占用的内存空间时不提供任何类型的安全性。我将我的解决方案与线程安全单例模式的一些示例结合起来,并提出了这个包装器,它将作为服务定位器:
public class NinjectResolver
{
private static object syncRoot = new object();
private static volatile NinjectResolver instance = null;
private static volatile IKernel kernel = null;
public static NinjectResolver GetInstance()
{
lock (syncRoot)
{
if (instance == null)
instance = new NinjectResolver();
}
return instance;
}
static NinjectResolver()
{
lock (syncRoot)
{
if (kernel == null)
kernel = new StandardKernel();
}
}
public void AddBindings(Dictionary<Type, Type> bindings)
{
lock (syncRoot)
{
foreach (var binding in bindings)
{
Type IType = binding.Key;
Type ImplementationType = binding.Value;
kernel.Bind(IType).To(ImplementationType);
}
}
}
private NinjectResolver()
{
}
/// <summary>
/// Resolves All dependencies for requested instance and returns that instance
/// </summary>
/// <typeparam name="T">Requested Implementation type</typeparam>
/// <returns>Instance of Implementation type</returns>
public T Resolve<T>()
{
return kernel.TryGet<T>();
}
/// <summary>
/// Resolves property injection dependencies in already instantiated Implementation types
/// </summary>
/// <param name="obj">Specified instance of implementation type</param>
public void Inject(object obj)
{
kernel.Inject(obj);
}
}
我的问题是:我是否需要在指定位置使用锁定,因为初始化将在 内部进行>App.xaml.cs (第一次调用 GetInstance() ),这些静态字段是否需要声明为 易失性 或者我可以省略该部分,因为他们或多或少是只读的 建造。如果有人能对此有所了解,我将不胜感激。
I Created a wrapper for Ninject DI container which I intend to use in WPF application. I would like it to be thread safe in case I need to open new windows in separated threads, but I am confused about using volatile keyword and locking. As much as I'm aware of, locking is pretty much Straightforward to understand but I'm not shore about using volatile keyword. From my googling results I came to understanding that volatile keyword ensures safe read access for specified instance in multithreaded environment but doesn't provide any kind of safety when making changes in memory space occupied by the specified instance. I combined my solution with some examples of thread-safe singleton patterns and came up with this wrapper that would serve me as a service locator:
public class NinjectResolver
{
private static object syncRoot = new object();
private static volatile NinjectResolver instance = null;
private static volatile IKernel kernel = null;
public static NinjectResolver GetInstance()
{
lock (syncRoot)
{
if (instance == null)
instance = new NinjectResolver();
}
return instance;
}
static NinjectResolver()
{
lock (syncRoot)
{
if (kernel == null)
kernel = new StandardKernel();
}
}
public void AddBindings(Dictionary<Type, Type> bindings)
{
lock (syncRoot)
{
foreach (var binding in bindings)
{
Type IType = binding.Key;
Type ImplementationType = binding.Value;
kernel.Bind(IType).To(ImplementationType);
}
}
}
private NinjectResolver()
{
}
/// <summary>
/// Resolves All dependencies for requested instance and returns that instance
/// </summary>
/// <typeparam name="T">Requested Implementation type</typeparam>
/// <returns>Instance of Implementation type</returns>
public T Resolve<T>()
{
return kernel.TryGet<T>();
}
/// <summary>
/// Resolves property injection dependencies in already instantiated Implementation types
/// </summary>
/// <param name="obj">Specified instance of implementation type</param>
public void Inject(object obj)
{
kernel.Inject(obj);
}
}
My question is this: Do I need to use locking in specified places since initialization will take place inside App.xaml.cs (first call of GetInstance() ) and do these static fields need to be declared as volatile or I can omit that part since they are more or less readonly in this construction. I would appreciate if someone could shred some light on this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
要实现线程安全的单例模式,基本上有两个选择:
1.双重检查锁定
2.在声明时初始化实例
另外,您可以将代码放在静态块中,然后使用:
To implement a thread-safe singleton pattern you have two options basically:
1.Double-checked locking
2.Initialize the instance upon declaration
Also you can drop the code inside the static block and just use: