Entries
RSS 2.0

Comments
RSS 2.0

Playing Nice With Service Locators

When I introduce dependency injection to developers, I often receive the complaint that it’s not significantly better than the service locator pattern. The main disadvantage of a service locator is that you’re required to couple all of the services in your application to the service locator in order for them to resolve their dependencies. By using a DI framework instead, you can keep your services very loosely-coupled.

However, there are some advantages of the service locator pattern. In particular, it’s much easier to implement hybrid activation — when some of the values in a constructor are provided by the consuming code, and some are provided by the framework. Hybrid activation is common in situations where you don’t need (or want) your DI framework to control the instantiation behavior of the type, but you still want to be able to resolve dependencies that are required for the instance.

In Ninject, hybrid activation is possible through the use of context parameters, which allow you to provide values for specific constructor arguments when you request the instance. However, context parameters can only be used for active requests — that is, calls to the kernel’s Get() method. If you often call Get() on the kernel, you’re using it as a service locator anyway.

The reality is, there’s nothing inherently wrong with using a service locator — when used in the right way, it can greatly simplify your code. I don’t think that service locator and dependency injection are mutually exclusive; in fact, I’ve found that it can actually be very effective when used in conjunction with a dependency injection framework like Ninject.

For example, let’s say you have an EventWatcher service that listens for a named event on an IMessageBroker, reads event information from the message, and triggers a specified callback. The implementation of such a service might look like this:


public class EventWatcher<T> {
  public EventWatcher(string eventName, Action<T> callback, IMessageBroker messageBroker) {
    //...
  }
}

You can’t easily activate a service like this using the Ninject kernel (at least without using context parameters), since the first two constructor arguments have to be supplied from the consuming code, and only the third is actually a dependency that should be activated via the kernel.

However, let’s introduce a simple service locator, which just delegates activation requests to a Ninject kernel:


public static class ServiceLocator {
  private static IKernel _kernel;
  public static void Initialize(IKernel kernel) {
    _kernel = kernel;
  }
  public static T Get<T>() {
    return _kernel.Get<T>();
  }
  public static object Get(Type type) {
    return _kernel.Get(type);
  }
}

Then, when we initially create our kernel, we just have to pass it to the Initialize() method of the ServiceLocator:


public static class Program {
  public static void Main() {
    using (var kernel = new StandardKernel(...)) {
      ServiceLocator.Initialize(kernel);
      //...
    }
  }
}

Using the service locator, we can alter our implementation of EventWatcher to make it easy to pass in the event name and callback method arguments, while still leaving it flexible enough to swap out the implementation of IMessageBroker. This is particularly useful for testability, since you can easily swap in a mock implementation of IMessageBroker in your tests.


public class EventWatcher<T> {
  public EventWatcher(string eventName, Action<T> callback)
    : this(eventName, callback, ServiceLocator.Get<IMessageBroker>())
  { }
  [Inject]
  public EventWatcher(string eventName, Action<T> callback, IMessageBroker messageBroker) {
    //...
  }
}

As you can see, if the more limited constructor is called, the EventWatcher asks the ServiceLocator to resolve the instance that should be used. Notice also that I’ve still kept the [Inject] attribute on the second constructor, in case you want to activate the type using the kernel and context variables.

While this is a useful technique in limited use, it’s important to be careful how much you rely on it. Remember that every time you use a service locator instead of dependency injection, you’re coupling your type to the service locator — and since it’s a static method call, it’s coupled just about as tightly as you can get. Again, though, taken in small doses, this technique can actually simplify your code and make it much more flexible.

Attributes? We Don’t Need No Stinkin’ Attributes

Ninject will reach 1.0 later this month. As the project has gained traction, I’ve received a common complaint concerning the use of the [Inject] attribute to decorate dependencies. Ninject was originally designed to match my own tastes, and I don’t personally mind the attribute in this case. The common argument against attributes is that it hurts the readability of your code, but I would suggest that in this case it actually improves its readability by making it more declarative. At a minimum, it says “this value comes from somewhere special,” so even if there are other developers working with your codebase that don’t entirely understand dependency injection, the use of [Inject] is enough to get them asking questions.

However, while I would consider Ninject to be opinionated software, I also want to make sure it’s useful to people with differing tastes, as long as I can do so without sacrificing the common case. To that end, I’ve been working to make it easier to dodge the attribute requirement. There are actually four different ways of avoiding the use of [Inject], depending on the level of control you want over your codebase. Note that this article describes features available in the subverison trunk, which will become version 1.0 with very few modifications, but most are not available in RC1. However, I do my utmost to make sure that the trunk build of Ninject remains stable, and I am currently using it in production applications without trouble.

1. Use Automatic Constructor Injection

The first, and easiest way to avoid the attribute is to use automatic constructor injection. If a type only has a single constructor, Ninject will attempt to inject it regardless of whether or not it is decorated with an [Inject] attribute. Therefore, if you’re willing to accept the limitation of only using constructor injection, you can avoid using [Inject] anywhere in your code.

2. Use a Custom Injection Attribute

If it’s not the requirement of the attribute that bothers you, but the fact that it means you have to have a dependency on Ninject.Core throughout your code, you can customize the attribute that Ninject will look for to inject dependencies. This is done via KernelOptions. For example:


public class MyInjectAttribute : Attribute {}

public static class Program {
  public static void Main() {
    var options = new KernelOptions { InjectAttributeType = typeof(MyInjectAttribute) };
    var kernel = new StandardKernel(options, ...);
  }
}

Now, rather than decorating your dependencies with [Inject], you instead use [MyInject], and avoid the dependency on Ninject.Core. If you use optional dependencies, you can override the [Optional] attribute in this way as well.

3. Use the Auto-Wiring Extension

A recent addition to Ninject is Ninject.Extensions.AutoWiring, which provides a way to inject dependencies without ever needing to decorate them with attributes. Instead, which dependencies that are injected will be based on what bindings you register with the kernel. When a type is activated, Ninject will do the following things:

  1. It will find a constructor on the type whose parameters all have types for which bindings are registered. If there are multiple constructors available, it will select the one with the most parameters with bindings defined.
  2. Similar logic will be applied to methods — if the type defines methods whose parameters all have valid bindings defined, dependencies will be resolved for the arguments and the methods will be called.
  3. Finally, all properties and fields will be considered as well. If their types have bindings defined, they will be injected.

To use auto-wiring, you just need to load the AutoWiringModule into your kernel, and the extension re-wires the kernel components as necessary. A couple caveats:

  1. Auto-wiring does not work with implicit self-binding, so you will have to explicitly register self-bindings for all of your types to get Ninject to resolve them.
  2. As you might imagine, auto-wiring will slow down activation. However, it’s unlikely you’ll notice a change in performance unless you’re activating millions of instances via Ninject — and if you are, you might want to rethink your design. :)
4. Roll Your Own Heuristics

Ninject is designed to be ultra-customizable. The core is built around a collection of kernel components, which the kernel orchestrates in order to activate types, resolve dependencies, and do all the fun stuff that you’ve come to love from Ninject. My latest work leading up to 1.0 has been to adjust the model of Ninject to favor composition more over inheritance (a good design principle in general, by the way). Ninject ships with a collection of standard implementations of components, but you are free to remove them and replace them with your own custom implementations. Since most of the components are very granular, this is easier than it may seem… all you need to do is create a type that implements one of the components’ interfaces, and connect them to your kernel.

There are four components, called selection heuristics, that can be replaced to customize which members are chosen for injection. As you might imagine, they are:

  1. IConstructorHeuristic
  2. IPropertyHeuristic
  3. IMethodHeuristic
  4. IFieldHeuristic

You may replace any or all of these to take full control over which members are injected. If you’d like to see an example of how to implement your own selection heuristics, take a glance at the code for the auto-wiring extension. (All the extension does is plug in its own selection heuristics when you load the AutoWiringModule.)

As always, if you have questions about any of this, feel free email me at nkohari at gmail dot com or find me on Twitter, and I’d be happy to help!

Cleveland Day of .NET Aftermath

Yesterday, I presented at the first annual Cleveland Day of .NET in Beachwood, and it was a fantastic experience. I was able to meet some brilliant people — although at times it was a little surreal, since I already “knew” them from Twitter and it was like I was meeting them all over again. The presentations that I attended were all excellent, and the conversations in the hallways and at lunch and dinner were even better.

Off the top of my head, it was great to meet: Dan Hounshell, Alan Stevens, Joe Fiorini, Mike Eaton, Leon Gersing, Sarah Dutkiewicz, John Stockton, Corey Haines, and Brian Prince. I know that I’ve forgotten some people from this list, and I’m sorry… the day was really a whirlwind, and my memory is horrible. If I’ve forgotten you, please post a comment or send me a tweet and I’ll make it right! Thanks very much to everyone involved in organizing, sponsoring, and attending the event.

For my first time presenting in front of a larger audience, I felt like it went pretty well. I was admittedly a little intimidated — although very excited — when it ended up being standing-room-only during my presentation. Thanks to everyone that came to watch me speak, and I hope you found it useful! Thanks also for the kind words and great feedback afterwards, and a special thanks to Alan Stevens for “refactoring” the projector when it decided to overheat halfway through. :D

Here are my slides, and you can also download them below:

As promised, a more complex code sample that illustrates some of the principles I discussed in the talk is available to download here. The code sample illustrates some of the more advanced uses of Ninject — stuff that I never could fit on a Keynote slide. I encourage you to tear it apart and get your hands dirty. The best way to learn the value of IoC is definitely to try it for yourself.

Slides (Keynote): designing-for-change.key.zip
Slides (PDF): designing-for-change.pdf.zip
Sample project: wargame.zip

Great IoC Presentation by Justin Etheredge

Justin Etheredge gave a great presentation on dependency injection and inversion of control last week at the Richmond Code Camp. It gives a very good introduction to DI, which is something that I’m going to try to tackle at the Cleveland Day of .NET in a few weeks. Plus, he uses Ninject in the examples and was kind enough to quote me in the presentation, so it’s got to be good, right? :)

Seriously, though, if you weren’t able to see the presentation, Justin’s posted the slides and related code samples on his blog. I highly recommend you check them out if you’re interested in learning more about dependency injection!

Come Hear Me Ramble

I will be speaking at the Cleveland Day of .NET on May 17th. If you’ve heard of this inversion of control and/or dependency injection stuff and would like to hear more, by all means come on up to sunny Cleveland! Here’s the abstract for my talk:

The old adage states that the only thing that remains constant is change, and nowhere is this more true than in software development. In this presentation, Nate Kohari describes how to apply the principles of inversion of control and dependency injection to create software that can adapt to changing requirements. Learn to break your monolithic app into loosely-coupled, highly-cohesive pieces… then glue them back together with an inversion of control container to create ultra-flexible code that you can bend to your will.

If you’ve never used dependency injection, this talk should prove to be a good introduction, and I’ll be happy to answer any and all questions. Or, if you’re already experienced with dependency injection, come see how Ninject can free you from the pain of XML!

Also, I’m still relatively new to public speaking, so there’s always the chance that I’ll completely choke and you can throw tomatoes. What’s more fun than that?

Announcing Ninject Contrib!

A few days ago, I accepted the first patch for Ninject, an NLog integration extension by Ivan Porto Carrero. Ivan subsequently created a couple other extensions for Ninject, and rather than put them directly into the main project, we decided to launch Ninject Contrib to collect contributions from the community.

If you’ve got any ideas for Ninject extensions, or if you come up with any examples that you’d like to share with the rest of Ninject users, feel free to post your idea in the Ninject developers group and I’ll set you up with commit access.

Major thanks to Ivan for his contributions, and his excellent ongoing series of Ninject-related articles!

Extension Methods in .NET 2.0

One of my favorite new features of C# 3.0 are extension methods. However, for some projects I’m not willing or able to target version 3.5 of the .NET framework. Up until today I thought that this meant I was out of luck in terms of being able to use extension methods, until Scott Hanselman’s post about them got the gears turning in my head.

If you try to add an extension method in a project that targets version 2.0 of the .NET framework, you’ll get an error saying you have to reference System.Core. However, the error is misleading. Extension methods are just normal static methods tagged with the [Extension] attribute. This attribute is actually just added by the compiler behind the scenes. In .NET 3.5, it lives in System.Core, but if you define your own attribute like this:


namespace System.Runtime.CompilerServices
{
  [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
  public class ExtensionAttribute : Attribute
  {
  }
}

Your extension methods will suddenly spring to life! After testing, I realized I’m not the first one to figure this out, but it’s definitely something I’ll keep in my bag of tricks.

Frameworks and the Break-Even Point

I read a good post by Joel Ross the other day. In the post, Joel implements a simple project using Castle Windsor to drive dependency injection. In one of the comments, Matt Blodgett says that it seems like it takes a lot of code to implement, and that the code isn’t pretty. Naturally, I figured I’d use this an opportunity to point out the advantages of Ninject’s fluent interface vs. XML configuration. :)

The way I see it, every framework library has a cost that you have to pay up-front in order to use the library in your code. This cost might be in a learning curve, a performance penalty, or the fact that you have to write some boilerplate code to make the library work its magic. Typically, the argument is that by paying this up-front cost, you get a benefit that’s significantly larger. This creates a break-even point, where you make up for the “debt” you paid to use the library, and start becoming more effective because of it. The best libraries are the ones that keep the up-front cost as low as possible, so you reach your break-even point faster. Libraries that accomplish this goal can be used in significantly smaller projects, because it becomes easier to justify the up-front cost if you know that you’re going to quickly begin to see benefits in terms of efficiency.

Ninject was written to support enterprise applications, but aims to treat small projects as first-class citizens. To that end, I’ve gone to great pains to try to keep things simple in simple situations, and mask any complexity required for advanced scenarios from everyday use. Here’s the same example that Joel presented, written with Ninject.

First, the User class:


public class User {
  public IServiceApi Service { get; private set; }
  public string UserName { get; private set; }

  [Inject]
  public User(string userName, IServiceApi service) {
    UserName = userName;
    Service = service;
  }

  public void SendMessageTo(string message) {
    Service.SendMessage(String.Format("@{0} - {1}", UserName, message));
  }
}

One caveat: I typically try not to combine service logic with my domain model, and so I wouldn’t put the IServiceApi dependency directly in the User class. Not that there’s anything wrong with this, but it means that you have to activate every User that you load in your application via the DI framework, and that can interfere with scalability. It also makes activating the User a little bit more difficult, as you’ll see below.

Next, rather than creating the XML configuration to wire up the components, we create a module, and bind the IServiceApi interface to the TwitterApi implementation:


public class TwitterModule : StandardModule {
  public override void Load() {
    Bind<iserviceApi>().To<twitterApi>();
  }
}

(You could also add a self-binding for User, but you don’t have to since it’s a concrete type.) Maybe it’s just me, but those 4 lines of code (complete with IntelliSense!) are much simpler than the 20 or so lines of XML. You’re using a big powerful IDE, so why not take advantage of it to set up your DI framework?

Lastly, we need to load the module into a kernel and activate our User. Because of our userName parameter, we need to do a “hybrid” activation by passing a transient parameter to the Get() method. (This is what I meant about separating the domain model from the service model. It lets you avoid things like this.)


public static class Program {
  public static void Main() {
    IKernel kernel = new StandardKernel(new TwitterModule());
    User user = kernel.Get<user>(
      With.Parameters.ConstructorArgument("userName", "RossCode")
    );
    user.SendMessageTo("test");
  }
}

You could also just make the User’s UserName property writable, and set it after activating the object.

Now, this is a pretty simple example, and I’d say we still haven’t reached the break-even point with Ninject. However, if we had a couple more services like IServiceApi, each implementation of which had its own dependencies, the power of DI would start to make itself apparent. For example, consider the following scenario:

1. Our TwitterApi depends on a TwitterWebService.
2. We add a JabberApi which depends on a JabberClient.
3. We add a SmtpApi which depends on a SmtpClient, which depends on an EmailMessageFactory.

Assuming JabberClient, SmtpClient, and EmailMessageFactory are all concrete types, your existing application could support all of these new features without adding anything new to your type bindings. (This is because Ninject will automatically create “self-binding” when it encounters concrete dependencies.) You could then easily flip between the different options by altering the binding between IServiceApi and one of your *Api classes. Also, since your module is executable code like anything else, you could make it more intelligent, reading configuration files, command line parameters, or even a database to determine which messaging service implementation should be used.

The flexibility that inversion of control brings to your application benefits you the first time you need to add additional features, or make changes on the fly. Sometimes it’s difficult to understand what the benefit is by reading example code, and it takes some time to get used to writing your code to work with DI. It’s well worth the up-front cost though!

Ninject Release Candidate 1

I’ve been busy the past few evenings adding some features to Ninject to move it towards the impending 1.0 release. I’ve written about a few of them before, but here’s a quick breakdown of the changes.

Transient Parameters

Previously mentioned here and here, transient parameters provide a means to manipulate the activation process for active requests to the kernel’s Get() method. Since I previously wrote about them, I’ve rewritten the internals to generalize them. Now, you create custom parameters using the IParameter interface, and extensions or your bindings can read them and alter the activation process.

Aspect-Oriented Programming (Interceptors)

I briefly talked about this before also. Since dependency injection frameworks like Ninject already control object instantiation, it’s natural to add the ability to intercept method calls on the generated instances. I’d flirted with adding support in the past, but I was wary of spending the effort to write a large proxy-generation system. I was also concerned about bloating the core library, since not everyone will use interception.

Finally, I settled on "outsourcing" the hard part — proxy generation — to already-existing libraries like LinFu.DynamicProxy and Castle DynamicProxy2. The actual interception system is baked into Ninject.Core, but in order to actually use it you have to use one of these libraries and the corresponding integration extension. (You can also create your own integration, of course!)

There are two ways to define interceptors in Ninject: static and dynamic. Static interceptors are related to a single method, and are declared via attributes. The main attribute is InterceptAttribute, which can be used directly or extended to clean up the code. You can tag either a single method with an interception attribute, in which case only that method will be intercepted — or you can put the tag on the class itself, which will cause all methods on the type to be intercepted.

With Ninject’s history of fancy fluent interfaces, though, that’s way too boring. Naturally, I had to up the ante a bit, with what I call dynamic interceptors. These are defined kind of like bindings, in a module’s Load() method. If you’ve used the conditional binding system, you’re familiar with fluent interface rooted in the When class, that can be used to create binding conditions. Well, my super-secret plan has now been un-veiled; the same fluent interface can also be used to define dynamic interceptors.

There’s now a new method, like Bind(), available in modules, called Intercept(). This means that if you want to define dynamic interceptors, you can do things like this:


Intercept<cacheInterceptor>(When.Request.Method.ReturnType.EqualTo(typeof(int)));
Intercept<countInterceptor>(When.Request.Method.Name.StartsWith("F"));

As you might guess, the first registration will cause all method calls to any objects activated via the kernel to be intercepted by a CacheInterceptor. The second registration causes all methods starting with the letter "F" to be passed through a CountInterceptor. Naturally, these are contrived examples, but you can see the power available to you.

One more cool feature ties together the two fluent interfaces in a very interesting (at least to me!) way. If you do:


When.Request.Context

You can actually write conditions against the activation context (IContext) that the object that is being intercepted was activated in! (Whew. That’s a mouthful.) This means you can make interception decisions based on a type’s activation plan, or even transient parameters passed to the Get() method.

NOTE! This also means there’s a breaking change in the conditional binding system. Anywhere you were using When, you will now have to replace with When.Context. Sorry, I’ve been trying very hard to avoid breaking changes, but this one was necessary.

The new AOP support in Ninject deserves its own blog post (or series of blog posts). It’s one of my favorite new features, and I’ll continue to write about it as time goes on.

New Tracking Component and Scopes

I’ve refactored instance tracking, used for deterministic disposal, out of the kernel itself and into a new ITracker kernel component. I’ve also introduced a new scope system, which you can use for more fine-grained control over deterministic disposal:


IKernel kernel = ...
using (kernel.BeginScope())
{
  IService service = kernel.Get<iservice>();
}

The BeginScope() method returns an IScope object, which is disposable. As long as a scope is active, any instances that are created are registered in it. When the IScope is disposed, all instances that were created therein are passed to the kernel’s Release() method.

Extension Model

One of the driving forces of Ninject has been to keep the core library as slim as possible. This has resulted in a lot of additional assemblies, and until this point there hasn’t been a natural way to load them into the kernel. The new extension model uses the concept of Ninject modules as a plug-in architecture. For example, the pub/sub messaging system, which used to live in Ninject.Messaging, is now in Ninject.Extensions.MessageBroker. To use it, all you have to do is add the MessageBrokerModule to your kernel:


IKernel kernel = new StandardKernel(new MessageBrokerModule(), ...);

As more extensions are created, they will typically exposure an IModule that can be loaded into a kernel to extend it with the functionality provided by the extension.

Cleanup and Minor Enhancements

I’m starting to revamp parts of the code to take advantage of the syntax improvements available in C# 3.0 — particularly lambda methods rather than anonymous delegates. I’ve also spent some time moving some things around in the solution to get it more organized, including tinkering with namespaces to limit the types that are exposed to code that consumes Ninject and its extensions. I’ve also provided a strong-name key and signed all of the assemblies to allow them to be used in scenarios that require it.

I’m sure there’s a bunch of other things that I’ve added, but those are the ones that I can remember at the moment. If you’d like to tinker with Ninject, there’s a new build available on the project website, or you can check out the latest version from the trunk and build it yourself. I’d like to hear what everyone has to say about the new features. I’m targeting June for a final 1.0 release, and I’d like to know what you think is missing before we can call it the big one-oh.

Ninject and AOP

I put in some time last night and this morning to add the beginnings of interception/aspect-oriented programming support to Ninject. The development is being done in a feature branch off the main trunk, and is still pretty unstable, but feel free to check it out and let me know what you think.

As you might expect, Ninject’s interception support is attribute-driven, like most of the rest of the system. The first time a type is activated, both the class definition itself and all of its public methods are examined for any attributes that inherit from InterceptAttribute. These become part of the type’s activation plan in the same way as injection directives. If you decorate a single method with an interception attribute, only that method will be intercepted (obviously). However, if you put the attribute on the class, all of its public methods will be intercepted. There’s also a DoNotInterceptAttribute that can be added to method definitions to indicate that interceptions should be skipped for them.

More coming once I get the code a little more stable, but feel free to tinker in the meantime. By the way, if you’re interested in following the development of Ninject, or getting involved in the project, join one of the Google groups:

General discussion: http://groups.google.com/group/ninject
Development and commits: http://groups.google.com/group/ninject-dev

I’m always interested in hearing feedback and new ideas. Patches are also encouraged. :D