实现记录器范围而不发送依赖

时间:2016-11-21 13:11:46

标签: c# variables scope

我需要创建一个应该有范围的记录器(类似于TransactionScope类)。

这是一幅草图:

public class Logger
{
    private static Logger instance;

    public void BeginScope(string scopeName)
    {
        //...
    }

    public static Logger Instance()
    {
        // Singleton code
        return instance;
    }

    public void Log(string message)
    {
        Console.Writeline(string.Concat(scopeName, message));
    }

    public void EndScope()
    {
        //...
    }   
}

如何创建记录器范围,以便在我开始使用范围之后,如果我创建了许多类并在那里使用单例记录器,它将使用相同的范围,但不发送依赖关系?当我在类中登录时,我无法将范围用作依赖项。

如果我有代码:

for(var i = 0;i>2000;i++)
{
    Logger.BeginScope("scope_" + i);
    //create classes that contain methods that logs data
    Logger.EndScope();  
}

它应该在每个循环中创建一个范围。

2 个答案:

答案 0 :(得分:0)

鉴于所有日志记录都是通过Logger.Instance()进行的(即没有人保存该实例供以后使用),只需替换BeginScope中的实例:

public void BeginScope(string scopeName)
{
    _savedInstance = _instance;
    _instance = new LoggerForScope( scopeName );
}

public void EndScope()
{
    _instance = _savedInstance;
}

但这非常难看,如果范围重叠,将会失败。

编辑:

这个怎么样?使用范围进行记录。但是,您必须将记录器传递给想要记录的方法...

for(var i = 0;i<2000;i++)
{
    using (var scopedLogger = Logger.BeginScope("scope_" + i))
    {
        // use the scoped logger here
    }
 }

我猜,你不能同时拥有无处不在的静态实例和单独的范围。

答案 1 :(得分:0)

这是一幅草图:

public class Logger {
    // use thread local variable - will have separate instance per thread
    private static readonly ThreadLocal<Logger> _instance = new ThreadLocal<Logger>(() => new Logger());
    // scopes stack
    private readonly Stack<string> _scopes = new Stack<string>();

    public static void BeginScope(string scopeName) {
        // push new scope to the stack
        _instance.Value._scopes.Push(scopeName);
    }

    public static void Log(string message) {
        // use scope from the top of the stack (first check if not null)
        Console.WriteLine(string.Concat(_instance.Value._scopes.Peek(), message));
    }

    public static void EndScope() {
        // remove scope from the top
        _instance.Value._scopes.Pop();
    }
}

测试:

for (var i = 0; i < 10; i++)
{
    Logger.BeginScope("scope_" + i);               
    Logger.Log("test");
    Logger.BeginScope("inner scope_" + i);
    Logger.Log("test");                
    Logger.EndScope();
    Logger.Log("test"); // back to scope_i
    Logger.EndScope();
}