Which pattern to use for logging? Dependency Injection or Service Locator?

后端 未结 9 946
别那么骄傲
别那么骄傲 2021-01-31 15:51

Consider this scenario. I have some business logic that now and then will be required to write to a log.

interface ILogger
{
    void Log(string stuff);
}

inte         


        
相关标签:
9条回答
  • 2021-01-31 15:52

    You could derive another type e.g. LoggableBusinessObject that takes a logger in its constructor. This means you only pass in the logger for objects that will use it:

    public class MyBusinessObject
    {
        private IDependency _dependency;
    
        public MyBusinessObject(IDependency dependency)   
        {   
            _dependency = dependency;   
        }   
    
        public virtual string DoSomething(string input)   
        {   
            // Process input   
            var info = _dependency.GetInfo();   
            var result = PerformInterestingStuff(input, info);   
            return result;   
        }   
    }
    
    public class LoggableBusinessObject : MyBusinessObject
    {
        private ILogger _logger;
    
        public LoggableBusinessObject(ILogger logger, IDependency dependency)
            : base(dependency)
        {
            _logger = logger;
        }
    
        public override string DoSomething(string input)
        {
            string result = base.DoSomething(input);
            if (result == "SomethingWeNeedToLog")
            {
                 _logger.Log(result);
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-31 15:55

    I would prefer Singleton Service.

    Dependency injection would clutter the constructor.

    If you can use AOP, that would be the best.

    0 讨论(0)
  • 2021-01-31 15:57

    DI would work nicely here. Another thing to look at would be AOP.

    0 讨论(0)
  • 2021-01-31 15:58

    The logger is clearly a service that your business logic depends upon, and should thus be treated as a dependency the same way you do with IDependency. Inject the logger in your constructor.

    Note: even though AOP is mentioned as the way to inject logging I do not agree that it is the solution in this case. AOP works great for execution tracing, but will never be a solution for logging as part of business logic.

    0 讨论(0)
  • 2021-01-31 16:01

    We switched all our Logging/Tracing to PostSharp (AOP framework) attributes. All you need to do to create logging for a method is add the attribute to it.

    Benefits:

    • Easy use of AOP
    • Clear separation of concerns
    • Happens at compile time -> Minimal performance impact

    Check out this.

    0 讨论(0)
  • 2021-01-31 16:08

    I personally do a mixture of both.

    Here are my conventions:

    • From a static context - Service Location
    • From an instance context - Dependency Injection

    I feel this gives me the right balance of testability. I find it a little harder to setup tests against classes that use Service Location than use DI, so this is why Service Location ends up being the exception rather than the rule. I'm consistent in its use, though, so it's not hard to remember what type of test I need to write.

    Some have raised the concern that DI tends to clutter constructors. I don't feel this is a problem, but if you feel this way, there are a number of alternatives that use DI, but avoid constructor parameters. Here is a list of Ninject's DI methods: http://ninject.codeplex.com/wikipage?title=Injection%20Patterns

    You'll find that most Inversion of Control containers have the same features as Ninject. I chose to show Ninject because they have the most concise samples.

    Hopefully this is helpful.

    Edit: To be clear, I use Unity and Common Service Locator. I have a singleton instance of my Unity container for DI and my implementation of IServiceLocator is simply a wrapper around that singleton Unity container. This way I don't have to do any type mappings twice or anything like that.

    I also don't find AOP to be particularly helpful beyond tracing. I like manual logging better simply for its clarity. I know that most AOP logging frameworks are capable of both, but I don't need the former (AOP's bread and butter) most of the time. This is just personal preference, of course.

    0 讨论(0)
提交回复
热议问题