【问题标题】:How to share an instance of a class with many classes?如何与多个类共享一个类的实例?
【发布时间】:2012-07-10 23:54:19
【问题描述】:

我有一个 c# 网络服务。当我收到一个新请求时,我会创建一个日志记录实例。我有许多其他类的其他实例来处理请求,我希望它们也能记录下来。共享日志实例而不将其传递给构造函数或属性的最佳方法是什么?

【问题讨论】:

  • 你使用什么日志框架?
  • 下面的答案很好(基本上使用静态实例,由单例保护)。但是,请考虑使用 DI 容器来管理它。让每个人的生活更轻松。

标签: c# logging instance


【解决方案1】:

通常使用某种静态类/属性来共享对象,而无需到处传递引用,例如:

public class Logger
{
    static Logger()
    {
        this.Instance - new Logger();
    }

    public static Logger Instance
    {
        get;
        private set;
    }

    // Other non-static members
}

用法:

Logger.Instance.Log();

通常这个(或者至少是这个的变体)被称为singleton pattern

上面有很多变化,例如在日志框架中,下面的细微变化比上面的更常见:

public class Logger
{
    static Logger()
    {
        this.Instance = new Logger();
    }

    public static Logger Instance
    {
        get;
        private set;
    }

    public static void Log() 
    {
        Logger.Instance.Log();
    }
}

用法:

Logger.Log();

【讨论】:

  • 这是一个最优解;将 Logger 放在自己的库中,以便您可以从其他项目中引用它。
【解决方案2】:

Singleton Pattern is an anti-pattern;我想不出很多应该使用或推荐它的情况,包括在这种情况下,用于日志记录。

我们如何处理日志记录:一个日志记录实例通过构造函数注入注入到所有需要它的类中。例如:

public class MyClass
{
    private readonly ILogger _logger;

    public MyClass(ILogger logger)
    {
        _logger = logger;
    }

    public void DoStuff()
    {
        _logger.Trace("DoStuff called");
    }
}

注入的日志实例可以每次都是一个新实例,或者如果您一心想要拥有单个实例记录器,则可以创建一次并根据需要传递。

但是:我强烈推荐第一个选项,使用 DI 使用 Composition Root 模式构造您的类。我还建议使用日志框架,例如 NLog 或 log4net。这些是可配置的,并且易于与电子邮件、事件查看器、文件等一起使用。并且在多线程环境中工作。

我们有自己的ILogger定义,有Trace、Warn、Info、Exception等,然后用NLog实现了这个接口。这意味着我们可以通过创建 ILogger 的新实现然后进行简单的 DI 配置更新来轻松更改我们的日志记录方式。这是迄今为止对我们非常有效的一种日志记录解决方案。

【讨论】:

  • 这是一种低劣的方法——特别是如果你有几个类似的需求,你的构造函数会看起来很可笑。让你的班级拥有智能并自主决定他们的环境要好得多。整个 DI 理论是业余的和草率的。静态类没有任何问题,如果您正在编写 c#,当您引用任何 MS 核心程序集时,您已经完全绑定到它们。 String.Format() - 等等...不妨使用 Logging.Log()
  • 我明白你的意思,但我遇到的一个实际案例是 OAuth 访问令牌。不应命名的 API 仅允许每个刷新令牌每分钟使用 4 次,因此当我们的服务器在一分钟内发出 5 次以上的请求时,它一直在这样做,授权失败。但是,如果我在一个可以在组件之间共享的类上有一个可用的静态值,那么访问令牌可以使用一个小时来解决这个问题。
  • “如果你有几个类似的需求,你的构造函数会看起来很可笑”——构造函数注入让你的依赖可见。单例或静态类将它们隐藏起来。使用像 String.Format 这样的 MS 核心静态程序集与创建自己的静态类有很大不同,后者更有可能发生更改/失败。好的类设计应该限制需要注入的依赖的数量——这包括日志;如果你在构造函数中注入了太多东西,那么这个类可能做的太多了。
【解决方案3】:

单例模式。

即具有私有构造函数的类。您使用公共静态方法只创建一个类的实例并返回该对象。

编辑:还值得注意的是,您需要将此类放在自己的项目中,以便所有类都可以引用它。

【讨论】:

    【解决方案4】:

    好吧,您可以让您的日志记录类包含静态方法,这些方法实际写入内存/刷新到磁盘。您也可以查看Singleton Pattern

    【讨论】:

      【解决方案5】:

      您可以使用Singleton Pattern 确保整个系统中只有一个日志记录对象实例。

      将日志记录对象传递给构造函数或作为属性实际上会使您的代码更容易测试,具体取决于您实现单例模式的方式。日志记录是令人讨厌的横切关注点之一,总是需要权衡取舍。

      【讨论】:

        【解决方案6】:

        通常在每个类中创建一个新的记录器实例不是问题。 Log4Net 记录器构造函数将类型作为参数,以便为您提供更好的日志。

        【讨论】:

          【解决方案7】:

          使用静态字段(我假设 C# 支持这些)。语法应该是这样的:

          private static final Logger logger = new Logger(...);
          

          只要你需要在课堂上记录一些东西,就可以使用它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-02
            相关资源
            最近更新 更多