带有依赖注入的单例类c#

问题描述 投票:0回答:2

我们有一个带有 QCServiceLog 类的外部项目,该类具有由 Unity 解决的 ILogging 依赖项。 但 QCServiceLog 是一个 Singleton 类,如以下示例所示:

private readonly ILogging _logging = null;

private static QCServiceLog _instance = null;
public static QCServiceLog Instance
{
    get
    {
        return _instance;
    }
}

public QCServiceLog(ILogging logging)
{
    _logging = logging;
    if (_instance == null)
    {
        _instance = this;
    }
}

我们正在尝试使用它,在我们的解决方案中,我们进行了如下注册:

uc.RegisterType<ILogging, QCFileManager>(new ContainerControlledLifetimeManager());

但是由于 QCServiceLog 是单例,我们认为代码永远不会通过构造函数,因此 _instance 永远不会被实例化。 我们正在使用它来执行此操作:

QCServiceLog.Instance.Log(ex);

单例实现正确吗?我们相信它永远不会对 QCServiceLog 进行new

你觉得怎么样?有什么我们可以在不改变外部项目的情况下做的事情吗? 您可以想象的例外是:

未将对象引用设置为对象的实例。

我非常感谢您的帮助!

dependency-injection singleton unity-container
2个回答
4
投票

您提供的代码不是线程安全的 - 请看这里 在 C# 中实现单例模式:

public QCServiceLog(ILogging logging)
{
    _logging = logging;
    if (_instance == null)
    {
        _instance = this;
    }
}

另一个问题是构造函数没有隐藏。因此,即使您的 IoC 容器将该类注册为 Singleton,仍然可以使用

new
运算符在代码中的任何位置构造此类的实例。我在我开发的一个应用程序中发现了由这件事引起的内存泄漏(目的是通过 DI/IoC 使用,它注册为单例,但通过代码手动更新。


2
投票

单例实现正确吗?

是的。但它需要先从容器中实例化,然后才能获取它的静态实例。

换句话说,你不能使用这一行:

QCServiceLog.Instance.Log(ex);

直到您第一次致电:

container.Resolve<QCServiceLog>();

(假设您已使用 Unity 注册了

ILogging
的实例),因为第一次调用不会命中构造函数来填充
_instance
值。

您最好直接将其注入需要的地方:

public class Foo(QCServiceLog log)

或者创建一个包装类,其中包含在使用它之前正确连接它的逻辑,并通过 DI 容器注入。

无论哪种方式,您应该注意 DI 主要用于您的应用程序。 3rd 方实用程序不一定以 DI 友好的方式执行操作,因此您可能需要使用 facadeadapter 以使它们在您的应用程序上下文中使用 DI 友好。

© www.soinside.com 2019 - 2024. All rights reserved.