The dependency injection pattern is a complicated pattern,
one that I do not fully understand yet. I first came across the pattern at http://www.martinfowler.com/articles/injection.html,
and since then I am starting to get a glimpse of how it can work. It works through
reflection and attributes. Let me explain further.
Inversion of Control (IOC) works by getting a reference to a
particular object dynamically. It identifies the object through the use of
attributes. An attribute is defined for a constructor, a property, or even the
individual parameter of a constructor or method, that marks that object as
needing a dynamic reference. The parent object, which uses reflection to
inspect the metadata for the class, finds the attributes, gets a reference of
the specific object type, and passes it in to the member.
Let us break this down some. There has to be some governing
object that knows how to get a reference to a specific object marked through an
attribute. The dynamic reference could be a derivative of the member's type
that has the attribute. You will see this in the Composite UI Application Block
(CAB); a module uses a work item, not the base class (WorkItem) but the derived
class that the custom module defines. The module is linked to the derived work
item through a code declaration, and the instance of the derived work item
class is dynamically created through the Activator statements shown above.
I could also see how a specific instance of an object would
be desired as well, which would require some sort of notation in the attribute
to define this. For instance, you may have a requirement to get a reference to
a user object that represents "John Doe" and not just any user object
reference. The attribute would need some way to denote this, and since
attributes are not generated dynamically, it may not be possible; unless the
application uses code to create a link between the governing object and an
injected object, say through the configuration file or an XML file or some
sort.
Using Dependency Injection, a class could have the following
notation for a property that marks it as needing a new instance of an object
that matches the property type.
Listing 15
private UserInfo _user;
[CreateNew]
public UserInfo UserInformation
{
get
{
return _user;
}
set
{
_user = value;
}
}
For this to work, there needs to be a governing object at a
level above the UserInformation class that can parse the property, find the
CreateNew attribute and create a UserInfo object, passing it to the property's
setter. As another example, injection could occur for a method declaration.
Listing 16
[Injection]
public UserDetails[] GetUserDetails([ServiceDependency]UserInfo user)
{
//DO something
}
The Injection attribute marks a method requiring the need
for injection and the ServiceDependency attribute needs an injection of the
UserInfo object into it. The application also needs to be able to get a
reference to the UserInfo object that is part of the dependency (maybe defined
in another object) and pass it into the method call.
This is an extent of what some of the IOC frameworks can
do. There are several IOC frameworks freely available.
·
Composite UI Application Block
·
Spring .NET
·
StructureMap
·
Castle