【问题标题】:c# static class that uses another classc# 使用另一个类的静态类
【发布时间】:2016-12-16 20:14:54
【问题描述】:

我有一个记录器 API,可用于记录到文本。 记录器有一些属性,可用于记录事件类型(Info、Err 等)、源应用(app1、app2 等)和消息文本。

语法简单,运行良好:

Logger log = new Logger();
log.Write("Information", "SourceApplication", "Test text to log");

现在我正在考虑创建 2 个静态类,一个用于“通用日志记录”,另一个用于“调试日志记录”。目标是避免为每个模块利用率创建记录器对象的新实例。每个类都应该能够在不实例化的情况下使用这些对象(静态类应该自动处理)。

“调试日志” - 可以由解决方案中的任何项目使用,并且应该是单例。 要使用的呼叫者代码应该是:

LoggerDebug.Write("Debug", "Debugger", "Test text to log");

通用日志记录 - 供所有项目模块使用,但在每次使用后,静态类应处理 Logger 对象 要使用的呼叫者代码应该是:

LoggerDebug.Write("Information", "App1", "Test text to log");

我尝试从“Debug Logging”静态类开始,我读过 (http://csharpindepth.com/Articles/General/Singleton.aspx) 但我不确定这是否是正确的方法... 你能给我一些建议吗?

using System;
using System.Diagnostics;
using System.Collections.Generic;

namespace Common
{
    public sealed class LoggerDebug
    {
        private static LoggerDebug instance = null;
        private static readonly object padlock = new object();
        private static Logger log;

        static LoggerDebug Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new LoggerDebug();
                    }
                    return instance;
                }
            }
        }

        public LoggerDebug()
        {
            log = new Logger();
        }

        public static void Write(String EventType, string appSource, string text)
        {
            log.Write(EventType, appSource, string.Format("Test {0}", text));
        }
    }
}

调用者代码如下所示:

LoggerDebug.Write("Information", "App1", "Test text to log");

当我尝试运行应用程序时,它会崩溃:

“System.NullReferenceException”类型的未处理异常 发生在 Common.dll 附加信息:对象引用不 设置为对象的实例。

也就是说 ctor 没有实例化 log = new Logger();

所以我可以通过以下方式纠正这个问题:

private static Logger log = new Logger();

并评论 ctor 代码

public LoggerDebug()
{
    //log = new Logger();
}

但我很困惑,不确定这是否是正确的方法,如何正确地做到这一点?

我可以使用任何示例吗?

【问题讨论】:

  • 附带问题:为什么要重新发明轮子?有 2 个可用于 .NET 的优秀日志框架,分别称为 Log4NetNLog
  • 你的静态实例永远不会被调用。
  • 只需在静态方法“Write”中创建新实例
  • 扩展 RAZER 的观点 - LoggerDebug.Instance.Write("Information", "App1", "Test text to log");工作吗?
  • 正如我所说,如果我将属性更改为 并注释 Constructor 的代码,代码可以正常工作,但正如我所说,我的问题是我不确定这是否是正确的方法...

标签: c# logging exception-handling


【解决方案1】:

这是更新后的代码。由于没有实例成员/方法,因此使整个事物保持静态。查看代码中的 cmets。

在旁注中,我强烈建议您不要为学习体验以外的任何目的执行此操作。使用可高度配置且经过广泛测试的现有框架,例如 Log4Net 或 NLog。

using System;
using System.Diagnostics;
using System.Collections.Generic;

namespace Common
{
    // changed sealed to static as there are no instances
    public static class LoggerDebug
    {
        // removed lock object 
        private static Logger log;

        // added static constructor
        static LoggerDebug(){
            log = new Logger();
        }

        // no need for lock due to static constructor
        // removed Instance
        // removed instance constructor

        public static void Write(String EventType, string appSource, string text)
        {
            log.Write(EventType, appSource, string.Format("Test {0}", text));
        }
    }
}

或者,您可以使用单例模式,但您需要至少 1 个实例级别(非静态)成员才能使用它。

using System;
using System.Diagnostics;
using System.Collections.Generic;

namespace Common
{
    // changed sealed to static as there are no instances
    public sealed class LoggerDebug
    {
        // removed lock object 
        private static Logger log;

        // added static constructor
        static LoggerDebug(){
            log = new Logger();
            _logger = new LoggerDebug();
        }

        // singleton that is created only once
        private static LoggerDebug _logger;
        public static LoggerDebug Logger{
            get{return _logger;}
        }

        // removed static keyword
        public void Write(String EventType, string appSource, string text)
        {
            log.Write(EventType, appSource, string.Format("Test {0}", text));
        }
    }
}

您还可以像在示例中那样内联初始化静态字段。理想情况下,您永远不会希望初始化实例级别成员中的静态字段,因为可能存在竞争条件以及必须编写为每个实例执行的检查的费用,它效率不高,并且会导致代码脆弱。

【讨论】:

  • 伟大的帮助......这澄清了我脑海中的一些事情......谢谢:)
  • @user6495763 - 很高兴为您提供帮助。请使用左侧站点上的复选框将其标记为答案(如果您认为是)。
  • 在第一个示例中的“静态类”是由 C# 自动处理的对象实例“new Logger()”?
  • @user6495763 - 不,它是静态的,所以它永远不会被处理掉。一旦托管它的应用程序域被释放,它就会被释放,当您关闭应用程序或创建多个非默认应用程序域时会发生这种情况。
猜你喜欢
  • 2014-07-13
  • 1970-01-01
  • 2021-10-20
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多