目前我在c#中有一个自定义构建的静态日志类,可以用以下代码调用:
EventLogger.Log(EventLogger.EventType.Application, string.Format("AddData request from {0}", ipAddress));
当调用它时,它只会写入配置文件中指定的已定义日志文件。
然而,由于我必须记录很多很多事件,我的代码开始变得难以阅读,因为所有的日志消息。
是否有一种既定的方法或多或少地将日志代码从c#类中的对象和方法中分离出来,这样代码就不会变得难以控制?提前感谢大家的帮助,因为这是我最近一直在努力的事情
我喜欢PostSharp提供的AOP特性。在我看来,登录是任何一种软件的一个方面。日志记录不是应用程序应该提供的主要值。
所以在我的情况下,PostSharp一直都很好。春天。. NET也有一个AOP模块可以用来实现这一点。
我见过的最常用的技术是以这样或那样的形式使用AOP。
PostSharp是一个将IL编织作为AOP形式的产品,尽管不是在。net中实现AOP的唯一方法。
对此的解决方案是使用面向方面的编程,您可以在其中分离这些关注点。这是一个相当复杂/侵入性的改变,所以我不确定它在你的情况下是否可行。
我曾经有一个自定义构建的记录器,但最近更改为TracerX。这提供了一种简单的方法,可以根据不同的严重程度对代码进行检测。可以使用与您正在使用的类等密切相关的名称创建日志记录器
它有一个独立的查看器,具有许多过滤功能,包括日志记录器,严重性等。
http://tracerx.codeplex.com/这里有一篇关于它的文章:http://www.codeproject.com/KB/dotnet/TracerX.aspx
如果您的主要目标是记录函数进入/退出点以及两者之间的偶然信息,那么我使用Disposable日志对象已经取得了很好的结果,其中构造函数跟踪函数进入,而Dispose()跟踪退出。这允许调用代码简单地将每个方法的代码包装在单个using语句中。还为中间的任意日志提供了方法。下面是一个完整的c# ETW事件跟踪类以及函数入口/退出包装器:
using System;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace MyExample
{
// This class traces function entry/exit
// Constructor is used to automatically log function entry.
// Dispose is used to automatically log function exit.
// use "using(FnTraceWrap x = new FnTraceWrap()){ function code }" pattern for function entry/exit tracing
public class FnTraceWrap : IDisposable
{
string methodName;
string className;
private bool _disposed = false;
public FnTraceWrap()
{
StackFrame frame;
MethodBase method;
frame = new StackFrame(1);
method = frame.GetMethod();
this.methodName = method.Name;
this.className = method.DeclaringType.Name;
MyEventSourceClass.Log.TraceEnter(this.className, this.methodName);
}
public void TraceMessage(string format, params object[] args)
{
string message = String.Format(format, args);
MyEventSourceClass.Log.TraceMessage(message);
}
public void Dispose()
{
if (!this._disposed)
{
this._disposed = true;
MyEventSourceClass.Log.TraceExit(this.className, this.methodName);
}
}
}
[EventSource(Name = "MyEventSource")]
sealed class MyEventSourceClass : EventSource
{
// Global singleton instance
public static MyEventSourceClass Log = new MyEventSourceClass();
private MyEventSourceClass()
{
}
[Event(1, Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
public void TraceMessage(string message)
{
WriteEvent(1, message);
}
[Event(2, Message = "{0}({1}) - {2}: {3}", Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
public void TraceCodeLine([CallerFilePath] string filePath = "",
[CallerLineNumber] int line = 0,
[CallerMemberName] string memberName = "", string message = "")
{
WriteEvent(2, filePath, line, memberName, message);
}
// Function-level entry and exit tracing
[Event(3, Message = "Entering {0}.{1}", Opcode = EventOpcode.Start, Level = EventLevel.Informational)]
public void TraceEnter(string className, string methodName)
{
WriteEvent(3, className, methodName);
}
[Event(4, Message = "Exiting {0}.{1}", Opcode = EventOpcode.Stop, Level = EventLevel.Informational)]
public void TraceExit(string className, string methodName)
{
WriteEvent(4, className, methodName);
}
}
}
使用它的代码看起来像这样:
public void DoWork(string foo)
{
using (FnTraceWrap fnTrace = new FnTraceWrap())
{
fnTrace.TraceMessage("Doing work on {0}.", foo);
/*
code ...
*/
}
}
为了使代码可读,只记录您真正需要的内容(info/warning/error)。在开发期间记录调试消息,但在完成后删除大部分消息。对于跟踪日志记录,使用AOP来记录简单的事情,比如方法进入/退出(如果你觉得你需要那种粒度)。
的例子:
public int SomeMethod(int arg)
{
Log.Trace("SomeClass.SomeMethod({0}), entering",arg); // A
if (arg < 0)
{
arg = -arg;
Log.Warn("Negative arg {0} was corrected", arg); // B
}
Log.Trace("SomeClass.SomeMethod({0}), returning.",arg); // C
return 2*arg;
}
在这个例子中,唯一需要的日志语句是b。日志语句A和C是样板文件,你可以留给PostSharp来为你插入日志。
还有:在你的例子中,你可以看到有某种形式的"Action X被Y调用",这表明你的很多代码实际上可以移动到更高的级别(例如命令/过滤器)。
大量的日志记录语句可以告诉你一些事情:可以使用某种形式的设计模式,它也可以集中大量的日志记录。
void DoSomething(Command command, User user)
{
Log.Info("Command {0} invoked by {1}", command, user);
command.Process(user);
}
我认为在ASP中实现类似过滤器的东西是一个很好的选择。净MVC。这是借助属性和反射来实现的。你标记每一个方法,你想以某种方式登录和享受。我想可能会有更好的方法,可能是借助观察者模式或其他东西,但只要我想到它,我就想不出更好的方法。
基本上这样的问题被称为横切关注点,可以在AOP的帮助下解决。
我也认为一些有趣的继承模式可以应用于日志实体的基础,但我想要过滤器