Tuesday, May 15, 2012

Simplify Null-Reference Handling of Properties in C#

A few months ago I wrote about a simple design rule that helped us to get almost rid of this annoying "Object reference not set to an instance of an object" exception, here.

In this post I want to show another way to simplify the handling of null-references. In particular, collection properties that can be null.

Let's start with a small piece of code:
class Customer {
   public string Name { get; set; }
   public ICollection<Contact> Contacts { get; set; }
}

// ...

Customer customer = GetCustomer(1);
foreach (var contact in customer.Contacts)
   Console.WriteLine(contact.FirstName);

Looks fine and there seem to be nothing special to talk about. Due to the rule I showed in the other post, GetCustomer will never return null. Unfortunately, the Contacts property is still not guaranteed not to be null. If Contacts is null we are again in front of our old "friend" NullReferenceException.

The straight forward approach is to always add an if-condition to ensure that our property is set to any value before we can iterate through.
Customer customer = GetCustomer();
if (customer.Contacts != null) {
   foreach (var contact in customer.Contacts)
      Console.WriteLine(contact.FirstName);
}
My problem with this is that developers (like me) tend to be lazy. We don't want to always add the condition and the additional scope.

Wouldn't it be nice to be able to write something like this?
Customer customer = GetCustomer();
foreach (var contact in customer.Contacts.NotNull()) // <= notice the NotNull()
   Console.WriteLine(contact.FirstName);
Luckily .NET 4.0 makes this possible with a simple extension method. Extension methods are not only static at design-time, but also behave as any other static methods at run-time. Any call of an extension method on a null reference will be routed into the extension method without any reference validation.

Due to this behavior of .NET, we are able to create this very simple extension method.
public static IEnumerable<T> NotNull<T>(this IEnumerable<T> collection) {
   return collection ?? new T[0];
}

Yes, this only helps when iterating through the list. But, from my experience, this covers about 90% of use cases.

Attention, keep in mind to always return an empty, immutable collection - like an array. If you would return an instance of a List<T> you might run into unexpected behaviors. The list would not become assigned to the parent component and any changes would not take any effect to the parent.

Monday, May 14, 2012

Yet Another Dependency Injection Container

Well, this might sound odd to some of you. However, in this post I want to present yet another dependency injection (DI) container.

If you are doing fine with your's feel free to stop reading here. If there are some things that could do better or you are just interested in new options give me a chance.

Due to the fact that the containers feature set isn't that small anymore, this post is only a rough overview of some of its features. Please find a complete documentation attached at the bottom of this post.

Why Yet Another Dependency Injection Framework?

Yes, at first glance FluffyContainer (don't ask why this name) is yet another dependency container. However, FluffyContainer comes across with a combination of two aspects that I've been missing in other dependency injection (DI) frameworks until now.

By my experience there are two different kinds of DI frameworks out there. The one type is feature rich, but relatively slow in creation of objects. The other type are those that are really fast, but poor in features. FluffyContainer combines those two aspects.

Overview of Features

FluffyContainer supports all common DI framework features, like:
  • Type to type mappings (with and without named mappings)
  • Mapping to custom factories
  • Singleton behavior for mappings
  • Calling of parameterized constructors
  • Field injection
  • Property injection
  • XML based mapping configuration
  • In code mapping configuration

In addition to this, it also supports some more advanced features, like:
  • About 20 times faster than other containers
  • Caching of, once initialized, mappings to make the creation of the container very cheap
  • Two types of internal factories. One with focus on high performance and another one that focuses on low-trust environments (like in some ASP.NET environments)
  • Thread Singletons
  • The container and most of its related components are thread safe; including management of singletons
  • Custom type initialization by automatically calling a configurable init method
  • No need of referencing .NET DLLs like System.Web that would require a full .NET framework installation and wouldn't work with the client edition
  • Customization with builders (aka plug-ins)

Performance

One of the main reasons for the development of FluffyContainer was the bad performance of other DI frameworks. If DI can only be used to create the large components but has to be skipped for the smaller once it did not yet reach its target yet.

Whenever people argue that DI is slow, there is somebody else - often somebody who calls himself a matured Software Architect who explains that DI has nothing to do with performance. It is all about abstraction, coupling and composition. I disagree with those Architects! As long as I'm not able to abstract (almost) every component initialization with DI, there are always points of tight coupling that will need to be refactored when a new type hierarchy is required.

Nevertheless, there are always some massively performance critical parts of a system, where DI will most likely never become the shiny hammer. When it comes to arrays instead of lists, emit instead of reflection byte buffers and cost of stack allocation, you are on a point where DI will probably never the way to go. In this scenario, abstraction and composition in general is often the wrong decision. But in all other scenarios, performance should not the reason not to use it.

By default, FluffyContainer is about 20 times faster than the fastest other well-known DI frameworks. On top of this, it provides the possibility to create a factory for a specific mapping. With this factory the creation of components is about 90 times faster than other DI frameworks, while it still provides all features the container. The factory is about 80% (not times) slower than a hardcoded factory, what is a difference I can live with in majority of a system.

Here are some results of my performance tests with some other feature full DI frameworks. The X axis shows the count of items created in my tests, the Y axis shows the duration in milliseconds it took to create the instances.


If you wonder why you see only 3 lines, this is because the lines of "Hardcoded", "FluffyContainer" and "Fluffy Factory" are all overlaying at the bottom of the diagram.

Since this diagram doesn't tell you very much about the three lines on the bottom, here is another diagram that shows only those three competitors.


As you see, out of the box FluffyContainer is about 8.5 times slower than a hardcoded factory. If you know that you will need to create larger amounts of the same component it can be useful to take advantage of the available factories. Especially because the creation of a factory is really cheap.

If you prefer numbers over diagrams, here are my test results.
CountHardcodedFluffyContainerFluffy FactoryOther Fast DIOther Slow DI
500000109218158015106
10000002017535322030281
15000002825252463844591
20000004734574617261123

I'm not going to talk about the names of the other DI frameworks I used in this test since this is no bashing for any other framework. But trust me, the fast one is one of the fastest, serious DI frameworks.

Configuration

Here is a quick overview of how to configure the container in XML or in code.

FluffyContainer supports two different kinds of configuration; XML and a expression based in-code mapping syntax. Here is a short sample of both configurations.

XML
<?xml version="1.0" encoding="utf-8" ?>
<dependencies>
   <assemblies>
      <assembly name="System.Data, 
                      Version=4.0.0.0,
                      Culture=neutral,
                      PublicKeyToken=b77a5c561934e089"/>
      <assembly name="DependencyInjectionSamples"/>
   </assemblies>
   <namespaces>
      <namespace name="System.Data.Common"/>
      <namespace name="System.Data.SqlClient"/>
      <namespace name="DependencyInjectionSamples"/>
   </namespaces>
   <mappings>
      <map from="IMyComponent" to="MyComponent"/>
      <map from="DbConnection" to="SqlConnection" name="db1"/>
      <map from="IMyComponent" toFactory="MyComponentFactory" name="factory"/>

      <map from="IMyComponent" to="MyComponent" 
           singleton="appDomain" name="singleton"/>
      <map from="IMyComponent" to="MyComponent" 
           singleton="thread" name="threadSingleton"/>

      <map from="MyComponent" to="MyComponent" name="fpConst">
         <field name="_foo" value="123"/>
         <property name="Id" value="1"/>
      </map>
 
      <map from="MyComponent" to="MyComponent" name="fpMapped">
         <property name="Database" from="DbConnection"/>
      </map>
   </mappings>
</dependencies>
<!--
Read XML in C#
var resolver = XmlDependencyResolver.FromFile("DependencyInjection.xml");
FluffyContainer container = new FluffyContainer(resolver);
-->
C#
using FR.DependencyInjection;

...

FluffyContainer container = new FluffyContainer();
container.Map<IMyComponent>().To<MyComponent>();
container.Map<DbConnection>().Named("db1").To<SqlConnection>();
container.Map<IMyComponent>().Named("factory").ToFactory<MyComponentFactory>();

container.Map<IMyComponent>().Named("singleton").AsSingleton().To<MyComponent>();
container.Map<IMyComponent>().Named("thread").AsThreadSingleton().To<MyComponent>();

container.Map<IMyComponent>()
         .Named("fpConst")
         .WithField("_foo", 123)
         .WithProperty("Id", 1)
         .To<MyComponent>();

container.Map<IMyComponent>()
         .Named("fpMapped")
         .WithProperty("Database", typeof(DbConnection), null);

When using XML mappings, you are still able to add additional in-code mappings in code, after the container was initialized from an XML.

Usage

After configuring the container, you can use it in your project source code by using the Resolve method to create new instances. Use the Release method to ensure a correct clean-up of IDisposable implementing components, while taking singleton configurations into account.

var comp = container.Resolve<IMyComponent>();
// use comp
container.Release<IMyComponent>(comp);

To simplify error handling for disposable components, especially when working with more than one resource, consider using ActivationScope when resolving several components. The activation scope will automatically manage a disposing of all resolved instances when it runs out of scope.
using (ActivationScope scope = container.CreateScope()) {
   var comp2  = scope.Resolve<IMyComponent>();
   // do work
   scope.Release<IMyComponent>(comp2);
   // disposing of comp2 will be skipped when the scope becomes disposed
 
   // ..
 
   var mydb = scope.Resolve<DbConnection>();
   // do work
   // mydb becomes automatically disposed when the scope becomes disposed
}

Conclusion

As I stated at the beginning of this post; yes, this is yet another dependency injection (DI) framework. Nevertheless it is relatively grown in its set of features and its performance blows all other frameworks (that I know) out of the building. If you already successfully work with DI in your project, stay with whatever you use. If you start a new project or if you are completely new in DI, consider to give it a chance.

Don't forget to check the documentation related to this post that will describe all features of the framework in deep.

Download

FluffyContainer is part of my core libraries that I've published in another post, FR.Core Libraries.

Here you can find all files in the version that was used in this post: