编写包装类以获得松散耦合的更好方法

时间:2012-04-24 19:25:30

标签: c# generics log4net

class LogUtil<T> : ILogUtility
{
    log4net.ILog log;

    public LogUtil()
    {
        log = log4net.LogManager.GetLogger(typeof(T).FullName);
    }

    public void Log(LogType logtype, string message)
    {
        Console.WriteLine("logging coming from class {0} - message {1} " , typeof(T).FullName, message);
    }
}

public class Logger
{
    ILogUtility _logutility;

    public Logger(ILogUtility logutility)
    {
        _logutility = logutility;
    }


    public void Log(LogType logtype, string message)
    {
        _logutility.Log(logtype, message);
    }


}

我需要具备灵活的功能,并且能够在将来删除LogUtil类并使用其他功能。

所以我按如下方式编写LoggerUtility包装类:

class LoggerUtility<T>
{
    public Logger logger
    {
        get
        {

            LogUtil<T> logutil = new LogUtil<T>();

            Logger log = new Logger(logutil);

            return log;
        }
    }
}

我的客户端代码如下:

public class TestCode
{
    public void test()
    {

        new LoggerUtility<TestCode>().logger.Log(LogType.Info, "hello world");

    }

}

我正在编写可能不干净的Logger属性。

您可以看到以下行看起来不干净。

new LoggerUtility<TestCode>().logger.Log(LogType.Info, "hello world");

有没有更好的方法来编写客户端代码?我希望与LogUtil松散耦合,而不是直接在我的客户端代码中使用它。

请告诉我。

由于

2 个答案:

答案 0 :(得分:2)

注释中提供的答案是正确的(客户端应该依赖于接口ILogUtil而不是直接具体实现)。还有许多其他问题:

  • 每次登录邮件时,您都会实例化LoggerUtility<T> Logger类的新实例。也许这里的东西应该是静态的?额外图层(LoggerUtility)的重点是什么?

  • 您对泛型(LoggerUtility<T>)的使用并不完全有意义,因为您不必仅键入T,也不会使用该信息。

实际上,编写自己的日志记录是其他人已经花费的努力 - 只需使用现有的实现。我可以为log4netNLog担保,但如果您希望有灵活性,请在Castle.Services.Logging中找到适当的外观,其中包含适用于前面提到的实施的适配器(并且您可以自己写!)。

此处有更多信息:Is there a logging facade for the .NET world?

答案 1 :(得分:0)

取决于您希望日志包装器的行为有多复杂?

记录有多个级别,信息和例外是常态。

围绕使用Interfaces的答案100%正确,但也有DRY的原则(不要重复自己)。

如果您发现您的代码看起来非常重复,就像我的那样,那么可能在使用注入和接口等标准之后,还会在处理错误时实现Generic包装。

泛型允许您分离解决方案的逻辑并允许重用,接口允许您将日志记录的概念与物理实现分离。

  public static output ExecuteBlockwithLogging<output, input, config>(ExeBlock<output, input, config> exeBlock, input InputForExeBlock, ILoggingBlock logger)
    {

        exeBlock.Execute(InputForExeBlock);

        if ((exeBlock.logEntries != null) && (exeBlock.logEntries.Length > 0))
        {
            logger.Execute(exeBlock.logEntries);
        }


        if ((exeBlock.exceptions != null) && (exeBlock.exceptions.Length > 0))
        {
            foreach (var e in exeBlock.exceptions)
            {

                var dictionaryData = new Dictionary<string, string>();
                if (e.Data.Count > 0)
                {
                    foreach (DictionaryEntry d in e.Data)
                    {
                        dictionaryData.Add(d.Key.ToString(), d.Value.ToString());
                    }
                }

                var messages = e.FromHierarchy(ex => ex.InnerException).Select(ex => ex.Message);


                LoggingEntry LE = new LoggingEntry
                {
                    description = e.Message,
                    exceptionMessage = String.Join(Environment.NewLine, messages),
                    source = exeBlock.GetType().Name,
                    data = dictionaryData
                };

                logger.Execute(new LoggingEntry[] { LE });
            }
            return default(output);
        }

        return exeBlock.Result;
    }