其他分享
首页 > 其他分享> > CodeGo.net>为DI容器创建线程安全的单例包装

CodeGo.net>为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())内进行,我是否需要在指定的位置使用锁定,并且这些静态字段是否需要声明为volatile或我可以省略该部分?因为在此结构中它们或多或少是只读的.如果有人能对此有所了解,我将不胜感激.

解决方法:

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

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

标签:multithreading,ninject,wpf,c,net-4-0
来源: https://codeday.me/bug/20191201/2084599.html