为 DI 容器创建线程安全的单例包装器

发布于 2024-12-22 21:13:44 字数 2154 浏览 1 评论 0原文

我为 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

断肠人 2024-12-29 21:13:44

要实现线程安全的单例模式,基本上有两个选择:

1.双重检查锁定

public static NinjectResolver GetInstance()
{   
    if(instance == null)
    {
        lock (syncRoot)
        {
            if (instance == null)
                instance = new NinjectResolver();
        }
    }
    return instance;
}

2.在声明时初始化实例

private static volatile NinjectResolver instance = new NinjectResolver();

public static NinjectResolver GetInstance()
{
    return instance;
}

另外,您可以将代码放在静态块中,然后使用:

private static volatile IKernel kernel = new StandardKernel();

To implement a thread-safe singleton pattern you have two options basically:

1.Double-checked locking

public static NinjectResolver GetInstance()
{   
    if(instance == null)
    {
        lock (syncRoot)
        {
            if (instance == null)
                instance = new NinjectResolver();
        }
    }
    return instance;
}

2.Initialize the instance upon declaration

private static volatile NinjectResolver instance = new NinjectResolver();

public static NinjectResolver GetInstance()
{
    return instance;
}

Also you can drop the code inside the static block and just use:

private static volatile IKernel kernel = new StandardKernel();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文