【问题标题】:C# Reflection Vs. method AttributesC#反射与。方法属性
【发布时间】:2016-12-26 16:45:19
【问题描述】:

我正在尝试创建一个 Log4Net 包装器接口。接口代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PlayGround
{
    public interface ILogger
    {
        void SetSource(string typeName);

    /// <summary>
    /// Provide Log "message" and/or "exception" data only
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    /// <param name="memberName"></param>
    /// <param name="sourceFilePath"></param>
    /// <param name="sourceLineNumber"></param>
    void Error(string message, Exception exception = null,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = null,
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null,
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);

    /// <summary>
    /// Provide Log "message" and/or "exception" data only
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    /// <param name="memberName"></param>
    /// <param name="sourceFilePath"></param>
    /// <param name="sourceLineNumber"></param>
    void Warn(string message, Exception exception = null,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = null,
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null,
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);

    /// <summary>
    /// Provide Log "message" and/or "exception" data only
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    /// <param name="memberName"></param>
    /// <param name="sourceFilePath"></param>
    /// <param name="sourceLineNumber"></param>
    void Debug(string message, Exception exception = null,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = null,
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null,
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);

    /// <summary>
    /// Provide Log "message" and/or "exception" data only
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    /// <param name="memberName"></param>
    /// <param name="sourceFilePath"></param>
    /// <param name="sourceLineNumber"></param>
    void Info(string message, Exception exception = null,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = null,
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null,
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);

    /// <summary>
    /// Provide Log "message" and/or "exception" data only
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    /// <param name="memberName"></param>
    /// <param name="sourceFilePath"></param>
    /// <param name="sourceLineNumber"></param>
    void Fatal(string message, Exception exception = null,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = null,
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null,
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
    }
}

实现:

using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PlayGround
{
    class Log4NetLogger : ILogger
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Log4NetLogger));
        private static readonly bool isErrorEnabled = log.IsErrorEnabled;
        private static readonly bool isWarnEnabled = log.IsWarnEnabled;
        private static readonly bool isDebugEnabled = log.IsDebugEnabled;
        private static readonly bool isInfoEnabled = log.IsInfoEnabled;
        private static readonly bool isFatalEnabled = log.IsFatalEnabled;

    private string TypeName;

    public void SetSource(string typeName)
    {
        TypeName = typeName;
    }

    public void Error(string message, Exception Exception = null, string memberName = null, string sourceFilePath = null, int sourceLineNumber = 0)
    {
        if (isErrorEnabled)
        {
            string Message = BuildSourceDetails(message, memberName, sourceFilePath, sourceLineNumber);

            if (Exception != null)
            {
                Message += BuildExceptionMsg(Exception.Message);
            }

            log.Error(Message);
        }
    }

    public void Warn(string message, Exception Exception = null, string memberName = null, string sourceFilePath = null, int sourceLineNumber = 0)
    {
        if (isWarnEnabled)
        {
            string Message = BuildSourceDetails(message, memberName, sourceFilePath, sourceLineNumber);

            if (Exception != null)
            {
                Message += BuildExceptionMsg(Exception.Message);
            }

            log.Warn(Message);
        }
    }

    public void Debug(string message, Exception Exception = null, string memberName = null, string sourceFilePath = null, int sourceLineNumber = 0)
    {
        if (isDebugEnabled)
        {
            string Message = BuildSourceDetails(message, memberName, sourceFilePath, sourceLineNumber);

            if (Exception != null)
            {
                Message += BuildExceptionMsg(Exception.Message);
            }

            log.Debug(Message);
        }
    }

    public void Info(string message, Exception Exception = null, string memberName = null, string sourceFilePath = null, int sourceLineNumber = 0)
    {
        if (isInfoEnabled)
        {
            string Message = BuildSourceDetails(message, memberName, sourceFilePath, sourceLineNumber);

            if (Exception != null)
            {
                Message += BuildExceptionMsg(Exception.Message);
            }

            log.Info(Message);
        }
    }

    public void Fatal(string message, Exception Exception = null, string memberName = null, string sourceFilePath = null, int sourceLineNumber = 0)
    {
        if (isFatalEnabled)
        {
            string Message = BuildSourceDetails(message, memberName, sourceFilePath, sourceLineNumber);

            if (Exception != null)
            {
                Message += BuildExceptionMsg(Exception.Message);
            }

            log.Fatal(Message);
        }
    }

    private string BuildSourceDetails(string message, string memberName, string sourceFilePath, int sourceLineNumber)
    {
        return "[Class: " + TypeName + " Member: " + memberName + " Source: " + sourceFilePath + " Line: " + sourceLineNumber + "] [" + message + "]";
    }

        private string BuildExceptionMsg(string message)
        {
            return " [System Exception: " + message + "] ";
        }
    }
}

我相信从性能的角度来看,代码是基于我进行的在线研究而工作的。

问题是;而不是在接口中使用属性,是否有使用 C# 反射的方法,以便我可以将日志记录的代码仅移动到具体实现?这样界面更通用?

谢谢。

【问题讨论】:

  • 不确定真正想要什么。但是如果你迫切需要使用反射,堆栈跟踪(非常慢)总是可以提供相同的信息。
  • @leppie:是的,由于性能问题,我正在避免使用堆栈跟踪..
  • 猜你不想在调用代码中直接依赖 NLog。为什么不简单地使用 Facade 或 Adapter 设计模式?
  • @Chirdeep Tomar:我对 C# 比较陌生。你能提供例子吗? (这样我就可以掌握你提到的想法)。
  • @Guygar 请检查下面的答案。

标签: c# reflection interface attributes


【解决方案1】:

您可以使用两种设计模式中的任何一种,我更喜欢适配器。本质上,您正在创建一个接口,该接口在底层日志记录提供程序 Nlog 或 Serilog 上创建抽象。

http://www.dofactory.com/net/facade-design-pattern

http://www.dofactory.com/net/adapter-design-pattern

但我确信这个问题之前已经解决了一百万次。看看https://github.com/net-commons/common-logging

【讨论】:

    猜你喜欢
    • 2011-09-03
    • 2010-11-21
    • 2011-03-19
    • 1970-01-01
    • 2017-05-31
    • 2023-04-10
    • 2010-09-22
    • 2014-12-31
    • 1970-01-01
    相关资源
    最近更新 更多