Showing posts with label IoC. Show all posts
Showing posts with label IoC. Show all posts

Sunday, 22 April 2012

ASP.NET Web API Series - Part 4: Dependency Injection

[Level T2]

In this post, I will review the dependency injection features of the ASP.NET Web API. There are a few posts out there but I felt there are areas still not covered so I am exploring the dependency injection options. I do not try explaining what Dependency Injection (DI), Inversion of Control (IoC) or Service Location are. If you are not familiar with these you perhaps first need to get a grasp by reading numerous resources out there.

Until ASP.NET MVC 3 none of the Microsoft products had any IoC interoperability. In ASP.NET MVC 2 you had to resort to replacing default controller factory with your own and server controllers by using service location. In WCF you had to provide your own factories using code or config which were not great. But ASP.NET MVC 3 for the first time relinquish its hold on object creation and acknowledged the need for DI as more teams embraced it.

ASP.NET Web API beta has a built in support for dependency injection. Just be careful that there are breaking changes in the ASP.NET Web API source code and the model has changed (it has been simplified). I will shortly explain beta release and then move on to the source code which the final release will probably look more like it.

ASP.NET Web API beta release

[Remember, this stuff has changed] DI is based on setting a dependency resolver (technically a service locator) on the HttpConfiguration object. This object is on the GlobalConfiguration object as a static property (web hosting) or in case of self hosting on HttpSelfHostConfiguration.

So in case of web hosting you would use:
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(myResolver);
There are basically 3 options when it comes to registering a dependency resolver:

  1. An instance of an object implementing IDependencyResolver dependency which has two methods: GetService and GetServices
  2. An instance of an object which has these two public methods: GetInstance and GetAllInstances. No interface needed and Web API will use reflection to call methods.
  3. Passing two delegates that return an instance or instances for a particular type

ASP.NET Web API source code release

This has been simplified and unified so there is only one option: using IDependencyResolver

There is one change in IDependencyResolver though: in addition to GetServeice and GetServices (which now is in IDependencyScope interface implemented by IDependencyResolver), there is a BeginScope method. 

BeginScope according to documentation is:

Starts a resolution scope. Objects which are resolved in the given scope will belong to that scope, and when the scope is disposed, those objects are returned to the container. Implementers should return a new instance of IDependencyScope every time this method is called, unless the container does not have any concept of scope or resource release (in which case, it would be okay to return 'this', so long as the calls to are effectively NOOPs).
This is particularly important if you leave responsibility of lifetime management of your objects to your DI container.


Developing a simple Dependency Resolver for AutoFac


AutoFac is my DI framework of choice (I have used Windsor and Unity before). So here I will write a few lines of code to hook AutoFac into ASP.NET Web API.

All you need to do is to implement IDependencyResolver and then create an instance of your object and use SetResolver on the configuration (see above) instance.

Your Dependency Resolver is not supposed to throw exceptions but it can return null in case the type is not registered.

ASP.NET Web API also tries to use Dependency Resolver (and in case you have provided your own will use yours) to resolve its own dependencies. This could have placed a big burden on such a dependency resolver to have knowledge of all ASP.NET Web API dependencies but the implementation is as such that Web API will use the objects that you return for dependency resolution and if you return null, it will use the default.

So here is the code for the simple AutoFac dependency resolver:
public class AutoFacDependencyResolver : IDependencyResolver
{
 private ContainerBuilder _builder = new ContainerBuilder();
 private IContainer _container;

 public ContainerBuilder Builder
 {
  get
  {
   return _builder;
  }
 }

 public void Build()
 {
  _container = _builder.Build();
 }

 public IDependencyScope BeginScope()
 {
  return this;
 }

 public object GetService(Type serviceType)
 {
  object resolved = null;
  if (_container.TryResolve(serviceType, out resolved))
   return resolved;
  else
   return null;
 }

 public IEnumerable<object> GetServices(Type serviceType)
 {
  object resolved = false;
  Type all = typeof(IEnumerable<>).MakeGenericType(serviceType);
  if (_container.TryResolve(all, out resolved))
   return (IEnumerable<object>)resolved;
  else
   return null;

 }

 public void Dispose()
 {
  if(_container!=null)
  _container.Dispose();
 }
}
Things to note are:

  • We expose the builder so the client can register the components.
  • We expose Build() method so at the end of registration, Build() is called. Ideally we should hide the builder and expose it through AutoFactDependencyResolver methods so that build could not be directly called on the builder by the client.
  • AutoFac inherently does not have a ResolveAll method but instead you may resolve IEnumerable<T> in which case works as ResolveAll.
  • Please note that we had to use TryResolve so that no exception is thrown. Alternatively you may use a try/catch block and return null in the catch (but that could mask other exceptions)  
OK, let's imagine we have a controller which is dependent on loggers:

public interface ILogger
{
 void Log(string value);
}

public class TraceLogger : ILogger
{
 public void Log(string value)
 {
  Trace.WriteLine(value);
 }
}

public class DebugLogger : ILogger
{
 public void Log(string value)
 {
  Debug.WriteLine(value);
 }
}

public class DiTestController : ApiController
{
 private ILogger _logger;
 private List<Ilogger> _loggers;

 public DiTestController(IEnumerable<Ilogger> loggers)
 {
  _loggers = loggers.ToList();
 }

 public string Get()
 {
  _loggers.ForEach(x => x.Log("Get"));
  return "Dependency Injection";
 }

}

So the controller will use ForEach to call Log on all ILoggers passed to it. In order to register the Dependency Resolver, all we have to do is this:
AutoFacDependencyResolver resolver = new AutoFacDependencyResolver();
resolver.Builder.RegisterType<TraceLogger>().As<ILogger>();
resolver.Builder.RegisterType<DebugLogger>().As<ILogger>();
resolver.Builder.RegisterType<DiTestController>();
resolver.Build();
config.DependencyResolver = resolver;

Config object here is a reference to GlobalConfiguration.Configuration (in case of web hosting) or an instance of HttpSelfHostConfiguration (in case of self-hosting).

Conclusion

Dependency injection has gone through breaking changes from ASP.NET Web API beta to the source code release. Registering your own dependency injection provider is easy and all you need is to implement IDependencyResolver and then use SetResolver method on the HttpConfiguration (depending on your hosting scenario) to register it. ASP.NET Web API will optionally try using your resolver to resolve its own dependencies but you do not have to register the defaults. Be careful to catch any dependency resolution error.



Saturday, 7 April 2012

ASP.NET Web API beta Source code: Survival Guide

[Level T2]
NOTE on 01/06/2012: ASP.NET Web API RC was released last night (31/05/2012). This means for a while at least, you do not have to build the nightly releases. You can download it from here.

Just a quick note that as you probably know, ASP.NET Web API beta (along with ASP.NET MVC 4 beta) is out. Scott Guthrie announced the release in his blog on 27th of March and it has been released under Apache 2.0 license.

You may download the source code from here via git or web . This is a really good news for all who wanted to have a deep dive into the implementation and extensibility points of the framework - including me. The media was also surprised on the release as it shows perhaps another shift in Microsoft towards community-oriented software development - but I will leave this subject for another occasion.

It is interesting that the source code comes with full unit testing coverage, yet it does not use MS Test framework available in Visual Studio instead it uses xUnit, a framework among whose contributors is Brad Wilson. This gives us a bit more insight into the way ASP.NET team work who are arguably among the most popular teams in Microsoft.

Downloading the source is all fine. Yet I had a few teething issues with getting it working which I share so that others having similar problems could find their way out.

Building the framework source code

OK, as soon as you have downloaded and unzipped the source, just open the solution. Since this source relies heavily on NuGet packages yet it does not contain binaries, it needs to re-download the packages. There are instructions on the page but I personally could not get it working. 

So first thing to do is to right-click on the solution and click on "Enable NuGet Package Restore" as below [UPDATE: You actually can ignore this step, and do not have to set this value. I managed to build without this step]:


Now, if you attempt to build, you will get the error below:

error : NuGet package restore is not currently enabled. For more information, please see: http://aspnetwebstack.codeplex.com/wikipage?title=NuGet+Packages

Solution is to go to Tools -> Options -> Package Manager -> Package source and add the address below:

http://www.myget.org/F/f05dce941ae4485090b04586209c8b08/
Now you need to rebuild the packages as advised in the ASP.NET web stack page:

build RestorePackages

And now finally rebuild the solution and this time it will work. As the link above describes, this NuGet feed is not quite official and is used for out of band releases - which this source code certainly is.

Now you might get this error again if you try rebuilding having added the new NuGet feed. Not to worry, delete the source code, unzip again, Enable NuGet Package Restore and then build. This time should work.

Using Web API Source code

One of the best ways to understand a source code is to see it running and debugging it. And that is what I tried to do. 

I had already installed ASP.NET Web API/MVC beta from the installer. So here is what I did: created an ASP.NET Web API project (see Part 1 for more details), added the project to the Web API source code, removed references to the ASP.NET Web API/MVC beta DLLs and added project reference to those DLLs I needed from its source. Easy! Well, not so fast...

The problem is if you have installed the ASP.NET Web API, all binaries are already GACed and they take precedence over the project references. You can verify this by looking at the list of DLLs loaded in the output window while debugging. Now this by itself is not a problem, but considering the source to be newer with breaking changes, it becomes a different matteeeerrr...

Now courtesy of Christoph De Baene, this also has a solution. I was lucky to find about his post just from yesterday as he was quicker to see the problem and find a solution. He explains about using Environment variable so CLR looks the development path first:

To resolve this problem we can use DEVPATH. It’s an environment variable that you can set to a folder (typically you’re output folder). The runtime will use the DEVPATH folder for probing before looking into the GAC!

Setting DEVPATH environment variable


You also need to add the entry below to your config file (app.config or web.config depending on your project):
 

 <configuration>
   <runtime>
      <developmentMode developerInstallation="true"/>
   </runtime>
 <configuration>
 
OK, now it is time to run the code. Well, I ended up using Christoph's code but still having issues this time "Method not found":

Method not found: 'Boolean System.Net.Http.Headers.HttpHeaders.TryAddWithoutValidation(System.String, System.String)'.

Well, it turns out this time that the version of the System.Net.Http DLL has also moved on and I used the one coming with the installer. However, while Microsoft has decided not to include this assembly's source code along with the rest, source has indeed moved on and you need to use the one in the packages folder underneath the solution.

Now I did that and still not working! I was pulling my hair out and went through a few things and realised references were not set to "Copy Local". Once I set that to true, it started working.

Conclusion

The process of building and running the ASP.NET Web API (and MVC) is a bumpy ride. There are quite a few additional things you have got to do to get it working.

In brief, here are the steps you need to do to be able to debug the source code if you have installed ASP.NET Web API beta installer (see above for details):
  1. Create a DEVPATH environment variable and set to your debug output folder
  2. Add an entry to your config to flag VS to use DEVPATH
  3. Make sure all your references are "copy local" set to true
  4. Make sure you add reference System.Net.Http.dll using "Manage NuGet packages" and not from the GAC

Sunday, 25 March 2012

Dependency Injection for Singletons

[Level T2]

This is more of a hypothetical and perhaps philosophical question, but anyway I will shoot:
Now that most DI frameworks support singleton lifetime would you still manually implement the Singleton pattern?
I have seen a lot people answering NO to the question. They believe that the decision to use a singleton pattern can change and changing the lifetime of the object is just change in one line of code or configuration.

But I would answer YES.

Reality is, the reason to use Singleton pattern is usually:

  • Creating the object is expensive
  • Object uses (and commonly caches) data that are expensive to create
  • Object has to collect and keep some state/statistics
Which of above is likely to change over time? I would say practically none. When relying on DI frameworks to do the singleton pattern for you, your class loses its design coherency when it does not communicate its need to be implemented as singleton.


So I personally would implement the Singleton pattern and then register the instance (this is Windsor):

UniversalContainer.Container.Register(
    Component.For<IXsltTransformer>()
    .Instance(XsltTransformerWithCaching.Current)); // .Current is the singleton instance 

As it can be seen, the class XsltTransformerWithCaching is responsible for performing XSLT or XML documents. As we all know, XSLT processor in C# spits out the code for the transformation and builds an assembly at runtime (similar to Serialisation) and if done over and over again, it can cause "memory leaks". As we all know, once an assembly is loaded, it cannot be unloaded - and do not ask for it, it cannot be done.

So I would prefer to bake the singleton into the class.