Using structuremap with log4net wrapper

后端 未结 3 1262
南笙
南笙 2020-12-13 11:34

I have the following interface:

public interface ILogger
{
    void Debug(string message, params object[] values);
    void Info(string message, params objec         


        
相关标签:
3条回答
  • 2020-12-13 11:49

    We use a similar ILogger wrapper around log4net and typically use constructor injection. We use an interceptor as a factory method responsible for creating the Logger. Here is our typical registry for logging setup.

    public class CommonsRegistry : Registry
    {
        public CommonsRegistry()
        {
            For<ILogger>()
                .AlwaysUnique()
                .TheDefault.Is.ConstructedBy(s =>
                {
                    if (s.ParentType == null)
                        return new Log4NetLogger(s.BuildStack.Current.ConcreteType);
    
                    return new Log4NetLogger(s.ParentType);
                });
    
            var applicationPath = Path.GetDirectoryName(Assembly.GetAssembly(GetType()).Location);
            var configFile = new FileInfo(Path.Combine(applicationPath, "log4net.config"));
            XmlConfigurator.ConfigureAndWatch(configFile);
        }
    }
    

    The parent type null check is necessary when there are dependencies on concrete types.

    The rest is optional log4net setup stuff.

    One thing I do like about this setup is the ability to use a null loggers for unit testing.

    0 讨论(0)
  • 2020-12-13 12:01

    If the type parameter is context-specific, I don't think this is going to work as shown. If you need to pass something context specific in the constructor, you are likely going to have to create a factory interface and implementation that returns an instance of the ILogger:

    public interface ILoggerFactory
    {
        ILogger Create(Type type);   
    }
    
    public class LoggerFactory : ILoggerFactory
    {
        public ILogger Create(Type type)
        {
            return new Log4netLogger(type);
        }
    }
    

    It might be possible to bootstrap StructureMap to supply the instance you want based on the type, but that assumes a limited number of types that you know in advance.

    0 讨论(0)
  • 2020-12-13 12:13

    I really need to get out of the habit of answering my own question, but for those who run across it, here's the answer.

    return ObjectFactory.With(type).GetInstance<T>();
    

    I actually have a wrapper to structuremap (to avoid exposing the structuremap dependency to my app) that looks like the following:

    public static class ServiceManager
    {
        public static T Get<T>()
        {
            return ObjectFactory.GetInstance<T>();
        }
    
        public static T Get<T>(Type type)
        {
            return ObjectFactory.With(type).GetInstance<T>();
        }
    }
    

    Any time in the code I need a logger, I call the following:

    ServiceManager.Get<ILogger>(GetType()).Info("Logging page view...");
    
    0 讨论(0)
提交回复
热议问题