Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

There's this framework that I'm helping to design. There are some common tasks that should be done using some common components : Logging, Caching and raising events in particular.

I am not sure if it's better to use dependency injection and introduce all of these components to each service (as properties for example) or should I have some kind of meta data placed over each method of my services and use interception to do these common tasks?

Here's an example of both:

Injection:

public class MyService
{

public ILoggingService Logger{get;set;}

public IEventBroker EventBroker{get;set;}

public ICacheService Cache{get;set;}

public void DoSomething()
{
Logger.Log(myMessage);
EventBroker.Publish<EventType>();
Cache.Add(myObject);
}

}

and here's the other version:

Interception:

public class MyService
{

[Log("My message")]
[PublishEvent(typeof(EventType))]

public void DoSomething()
{

}
}

Here are my questions:

  1. Which solution is best for a complicated framework?
  2. If interception
    wins, what are my options to interact with internal values of a method (to use with cache service for example?)? can I use other ways rather than attributes to implement this behavior?
  3. Or maybe there can be other solutions to solve the problem?
share|improve this question

migrated from stackoverflow.com Mar 10 '12 at 15:16

This question came from our site for professional and enthusiast programmers.

2  
I don't have an opinion on 1 and 2, but regarding 3: consider looking into AoP (Aspect-oriented programming) and specifically into Spring.NET. –  AVIDeveloper Mar 10 '12 at 0:11
    
Just to clarify: you're looking for a comparison between Dependency Injection and Aspect Oriented Programming, correct? –  M.Babcock Mar 10 '12 at 0:13
    
@M.Babcock Haven't seen it that way myself but that's correct –  Beatles1692 Mar 10 '12 at 13:16
add comment

3 Answers

up vote 18 down vote accepted

Cross-cutting Concerns like logging, caching etc. are not dependencies, so shouldn't be injected into services. However, while most people then seem to reach for a full interleaving AOP framework, there's a nice design pattern for this: Decorator.

In the above example, let MyService implement the IMyService interface:

public interface IMyService
{
    void DoSomething();
}

public class MyService : IMyService
{
    public void DoSomething()
    {
        // Implementation goes here...
    }
}

This keeps the MyService class completely free of Cross-cutting Concerns, thus following the Single Responsibility Principle (SRP).

To apply logging, you can add a logging Decorator:

public class MyLogger : IMyService
{
    private readonly IMyService myService;
    private readonly ILoggingService logger;

    public MyLogger(IMyService myService, ILoggingService logger)
    {
        this.myService = myService;
        this.logger = logger;
    }

    public void DoSomething()
    {
        this.myService.DoSomething();
        this.logger.Log("something");
    }
}

You can implement caching, metering, eventing, etc. in the same way. Each Decorator does exactly one thing, so they also follow the SRP, and you can compose them in arbitrarily complex ways. E.g.

var service = new MyLogger(
    new LoggingService(),
    new CachingService(
        new Cache(),
        new MyService());
share|improve this answer
2  
The decorator pattern is a great way to keep those concerns separate, but if you have a LOT of services, that's where I would use an AOP tool like PostSharp or Castle.DynamicProxy, otherwise for each service class interface, I have to code the class AND a logger decorator, and each of those decorators could potentially be very similar boilerplate code (i.e. you get improved modularization/encapsulation, but you still are repeating yourself a lot). –  mgroves Mar 12 '12 at 17:19
1  
Agreed. I gave a talk last year that describes how to move from Decorators to AOP: channel9.msdn.com/Events/GOTO/GOTO-2011-Copenhagen/… –  Mark Seemann Mar 12 '12 at 17:30
add comment

I find the design of a framework to be largely orthogonal to this question--you should focus on the interface of your framework first, and perhaps as a background mental process consider how someone might actually consume it. You don't want to do something that prevents it from being used in clever ways, but it should only be an input into your framework design; one among many.

share|improve this answer
add comment

For a handful of services, I think Mark's answer is good: you won't have to learn or introduce any new 3rd party dependencies and you'll still be following good SOLID principles.

For a large amount of services, I would recommend an AOP tool like PostSharp or Castle DynamicProxy. PostSharp has a free (as in beer) version, and they just recently released PostSharp Toolkit for Diagnostics, (free as in beer AND speech) which will give you some logging features out of the box.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.