¿Cuál es el mejor diseño para esta clase?

assume this class:

public class Logger
{
    static TextWriter fs = null;

    public Logger(string path)
    {
        fs = File.CreateText(path);
    }

    public static void Log(Exception ex)
    {
        ///do logging
    }

    public static void Log(string text)
    {
        ///do logging
    }
}

and I have to use this like:

Logger log = new Logger(path);

Y luego usar Logger.Log() to log what I want. I just use one Logger. the question is: is this a good design? to instantiate a class and then always call it's static method? any suggestion yield in better design is appreciated.

Edit based on Marcla respuesta:

I flush on the last line of Log and there is no need for me to read the file while it is open, the issue with file not cleanly closed is right. this class simply satisfy my requirements and there is no need to be thread safe for it. I just want to get read of the instantiation part, I should get into the SetPath you said, any suggestion for closing file?

preguntado el 09 de enero de 11 a las 10:01

why reinvent the wheel? : use log4Net instead -

Are you trying to accomplish the use of a singular logger? -

@HPT: Read up on the singleton pattern. -

3 Respuestas

Yes, having a constructor just for this is bad design. A static SetPath method that can only be called once (else throws an exception) would seem better. You would set the path during app-startup, etc.

Then you can either make it a static class, or a singleton if it is required to satisfy some interface-based scenario.

Next: you deben add synchronisation here! That is not thread safe. If two threads attempt to log at the same time, I would expect this to collapse horribly. It doesn't need to be complex; at the simplest:

private readonly object syncLock = new object();
public static void Log(string value) {
    lock(syncLock) {
        //...
    }
}

(but note that this may incur some blocking costs; which can be improved with more sophisticated code - see below)

There are existing logging libraries that will think of lots more issues - file partitioning, async (to stop your code being blocked by IO), batching, etc; why not just use one of them? In particular, at te moment your file will not be cleanly closed at app-exit, doesn't flush regularly, and will keep the file locked most of the time. Not good.

Respondido el 09 de enero de 11 a las 14:01

I'd love some expanding on the synchronisation part. - alexn

@Marc: I flush on the last line of Log and there is no need for me to read the file while it is open, the issue with file not cleanly closed is right. this class simply satisfy my requirements and there is no need to be thread safe for it. I just want to get read of the instantiation part, I should get into the SetPath you said, any suggestion for closing file? - user415789

What libraries do you recommend for logging other, there is a list in google but which one you prefer - Kronass

@HPT - cada método estático debemos be thread safe. In particular, is this perhaps used in a web server scenario? - Marc Gravell ♦

@HPT if it is single thread, then the lock will never be contested. So I'd lock it de todos modos, and avoid the bugs when somebody adds a BackgroundWorker or ThreadPool use. - Marc Gravell ♦

No, this doesn't make sense. Each time a Logger is instantiated, the static TextWriter will be overwritten, which will affect all consumers of the class. If you want to keep the instance constructor then you should make the TextWriter an instance field and the methods should be instance methods.

As an alternative, you may want to consider using log4net, which will do this kind of logging work for you.

Respondido el 09 de enero de 11 a las 13:01

I think you should make whole class static with static property allowing you to set up the log path.

public static class Logger
{
    static TextWriter fs = null;

    public static string FileName
    {
      set
      {
        fs = File.CreateText(value);
      }
    }

    public static void Log(Exception ex)
    {
      if(fs == null) return;
        ///do logging
    }

    public static void Log(string text)
    {
      if(fs == null) return;
        ///do logging
    }
}

Respondido el 09 de enero de 11 a las 13:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.