by Jacob H. Hansen

Dependency injection using C# attributes

December 1, 2007 16:11 by Jacob H. Hansen

A class being dependant on another class is not uncommon. The dependency can be solved in a multitude of ways, but most common is passing references through the constructor.

However, when passing references through the constructor you are forcing yourself to consider the order of creating the objects – i.e. A has to be new’ed before B, if B is dependent on A. This was something I’d like to not have to worry about. Basically I wanted to be allowed being lazy.

First let me provide you with a little insight into the design of this application that is essentially an implementation of a component based system. (See: Mick West - “evolve your hierarchy”)

Everything revolves around Behaviors. These are exactly that by exposing very specific functionality. Next there’s the BehaviorGroups; behaviors are associated with groups, and thus groups make up a combination of different functionalities.

Often a behavior is dependent on another behavior, and this is exactly the problem I’m presenting a solution to in this post.

To mark a behavior type as a dependency for another behavior, you simply place the BehaviorDependency tag on a reference holder and it will be handled automatically. It reads like this:

  [BehaviorDependency]
  AnotherBehavior anotherBehavior; 

Likewise, you can specify dependencies across the system – i.e. behaviors that are associated with other groups.

  [BehaviorDependency(Group = “Another Group”)]
  AnotherBehavior anotherBehavior;

Essentially both of these blocks represent the same action:

  • Search group for association with behavior type
    • Found
      • Inject reference to the object
    • Not Found
      • Instantiate behavior, associate it with the group and inject reference to the object

The behavior itself is responsible for searching and finding fields marked with the dependency attribute. This is handled in the base-class, though, so code-wise there is little involvement required.

A more contextual example:

  public class SomeBehavior : Behavior
  {
      [BehaviorDependency]
      AnotherBehavior anotherBehavior;

      public override void Initialize()
      {
          base.Initialize();

          // AnotherBehavior has now been associated with this behavior’s group, and
      
    // anotherBehavior has been injected with the reference to the newly created
        
  // object
      }
  }

A few problems do arise, however. The most prominent one being that when a behavior is marked as a dependency it is assumed that this particular behavior implements an empty constructor. This is due to the instantiation of the behavior under the circumstance that the behavior has not yet been associated with the group. A minor annoyance if kept in mind and you simply code around it. The problem could possibly be solved using some further attribute magic, though.

Secondly, the references will not be injected until Initialize(). This effectively rules out using the constructor for anything that involves the dependencies. Again, not a huge problem when kept in mind.

All in all, I much prefer having an automatic way of doing this – and come on, you can’t say it isn’t just a tiny bit pretty to read.




Comments

NIlesh on June 27. 2008 10:37

Can you please send me the sample POC application that can give me end to end perspective of the implementation?
Thanks in advance.

Add comment