0

Suppose I have an utility (e.g. a logger) that might be used by every class in my app. I want the logger to be able to save the information about the client type that uses the logger i.e. if a StockProvider wants to log a message, the logger should append the StockProvider class name along with the log message. And the StockProvider has the logger passed via constructor like

public StockProvider (ILogger logger) {}

so it can use the logger in its methods. I know it's easiest to have the type information passed every time logger is used, like logger.Log (GetType(), msg). What I want is the logger to have that client type information in its state instead of having to pass that type info to logger methods so that calls to Log result in the message being appended the type name. E.g. passing it with a constructor like

class Logger : ILogger {
    public Logger (Type clientType) {
        this.type = clientType;
    }
    public void Log(string msg)
    { Console.WriteLine(this.type.FullName + msg); }
}

would work as then inside StockProvider I could just say

logger.Log (msg)

So the question is: am I able to register Logger in such a generic way that it receives the clientType of the client that requests the logger whether it is StockProvider or any other client type? Please notice that I used the logger just as an example of some class that might be widely used in the code. It might also be a kind of event publisher that would want to know who triggers an event

patryk
  • 651
  • 12
  • 30

2 Answers2

2

You can create a generic logger like:

    public interface ILogger<T> where T: class
    {
       void Log(string message, LogLevel level);
    }

    public class Logger<T> : ILogger<T>
       where T: class
    {
       public void Log(string message, LogLevel level) 
       {
            WriteLog(typeof(T).Name + ": " + message, level);
       }
    }

And now you have to register a generic implementation of ILogger in your DI container, for example in UnityContainer you can do it:

    IUnituContainer container = new UnityContainer()'
    container.RegisterType(typeof(ILogger<>), typeof(Logger<>));

Next your provider must look like:

    public StockProvider (ILogger<StockProvider> logger) {}
Mateusz Radny
  • 301
  • 1
  • 6
  • Cool. Actually I thought about such an approach but was wondering if I could get away without the type parameter. And that's the whole point of the question. Anyway thanks for the suggestion - a neat solution! – patryk Feb 08 '17 at 15:09
0

Using log4Net, You can do something like this:

public class Import 
{
    private static ILog Log
    {
        get
        {
            if (LogManager.GetCurrentLoggers().Length == 0)
            {
                // load logger config with XmlConfigurator
                log4net.Config.XmlConfigurator.Configure();
            }
            return LogManager.GetLogger(typeof(Import));
        }
    }

In my case Import is the name of my class as it is evident. You need to change this piece of code based on your need.

Payam
  • 741
  • 3
  • 14
  • 37
  • Honestly, I used logging just as an example of some implementation that is widely used. It might also be some kind of event publishing code that would need the info about who is publishing an event. The question is strictly about the DI registration and resolving concepts – patryk Feb 08 '17 at 15:07