代码之家  ›  专栏  ›  技术社区  ›  Ken

声明静态成员的类修饰符(例如,对于log4net)?

  •  5
  • Ken  · 技术社区  · 14 年前

    我使用的是log4net,我们的代码中有很多这样的东西:

    public class Foo {
        private static readonly ILog log = LogManager.GetLogger(typeof(Foo));
        ....
    }
    

    log4net FAQ 还提到了另一种可能性,这种可能性更为冗长:

    public class Foo {
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        ...
    }
    

    有没有可能编写一个decorator来定义这个?我想简单地说:

    [LogMe]  // or perhaps: [LogMe("log")]
    public class Foo {
        ...
    }
    

    我在其他语言中也做过类似的事情,但从来没有像C#这样的静态编译语言。我可以从装饰器定义类成员吗?

    编辑 :嘿。我是Lisp程序员。我很欣赏关于转换语言的建议,但实际上,如果我想转换语言以获得更好的元编程功能,我会一直使用Lisp而不是半途而废。不幸的是,使用不同的语言不是这个项目的一个选项。

    8 回复  |  直到 14 年前
        1
  •  5
  •   Igal Tabachnik    14 年前

    这正是面向AOP方面编程的任务。看一看 PostSharp ,这是一个.NETAOP框架,它允许您完全按照自己的意愿进行操作。

    编辑: 现在看来,PostSharp是一个商业产品。如果你正在寻找一个开源(免费)的解决方案,我建议 LinFu AOP .

        2
  •  3
  •   csharptest.net    14 年前

    我们使用几乎相同的东西:

    private static readonly ILog Logger = LogManager.GetLogger();
    

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static ILog GetLogger()
    {
        Type t;
        try { t = new StackFrame(1, false).GetMethod().DeclaringType; }
        catch { t = typeof(UnknownObject); }
        return GetLogger(t);
    }
    private static class UnknownObject { }
    

    事实证明,这更像是我愿意经历的痛苦。我更喜欢使用静态方法记录的静态对象。如果您没有获取文件信息,那么获取调用方法的成本就没有那么高。与仅仅调用Log4Net的开销相比,获取调用类型不算什么(取决于所使用的记录器)。

        3
  •  1
  •   dtb    14 年前

    Attributes 属性是元数据

        4
  •  1
  •   Mark    14 年前

    我们包装了log4net,这样就可以轻松地将其切换出来。这是我们将来很可能改变主意的事情。

    var callingType = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().DeclaringType
    

    如果您对日志记录的方式很聪明,那么只有在需要日志消息时,您才可能产生这种成本。

        5
  •  0
  •   rossipedia    14 年前
        6
  •  0
  •   David    14 年前

        7
  •  0
  •   JasonTrue    14 年前

    您可能可以借助 PostSharp

    在Boo中使用宏是非常简单的,但这对您的情况没有多大帮助。

        8
  •  0
  •   Tim Jarvis    14 年前

    也许一个简单的方法是在接口上编写一个扩展方法,然后您的类只需要“实现”接口(但实际上不是因为扩展实现接口)

    public class Foo : IGetLog<Foo>
    {
    
    }
    

      public interface IGetLog<T> { }
    
      public static class IGetLogExtension
      {
        public static ILog GetLogger<T>(this IGetLog<T> getLog)
        {
          return LogManager.GetLogger(typeof(T));
        }
      }