Note: A full solution is supplied at the bottom of this post if you would like to download it and run it.
A couple of days ago Matt wrote about the new Unity Application Block. The Unity MSDN article describes Unity as:
The Unity Application Block (Unity) is a lightweight, extensible dependency injection container. It facilitates building loosely coupled applications and provides developers with the following advantages:
- Simplified object creation, especially for hierarchical object structures and dependencies
- Abstraction of requirements; this allows developers to specify dependencies at run time or in configuration and simplify management of crosscutting concerns
- Increased flexibility by deferring component configuration to the container
- Service location capability; this allows clients to store or cache the container
Designing a software system architecture with loosely coupled components makes life easier in the long run. A few of the benefits of loose coupling are : maximizing testability, modularizing components, and increase the maintainability of the code.
This is a simple introduction into Unity that exemplifies the simplicity of the container setup. I will cover two options for type registration:
- Manual Method based type Registration
- Configuration file (XML Based) type Registration
The Example Application
The application that is included at the bottom of this post is visualized via the class diagram below. This simple application utilizes very simple implementations of the repository, mapper, domain model, data transfer object (DTO) and service layer patterns for example purposes.
The application follows a very simple flow as shown below:
The console application calls into the Service layer which calls into the repository to get the data which calls into the DB. A domain object is created from the Repository call, which is passed up to the service layer. The Service layer returns a DTO via the DTO Mapper to the parent caller (the console app) and then the console app displays the customer name via a write line call.
None of these layers have any inter-dependent dependencies coded inside of them. I'm using constructor injection to inject dependencies into the calling object.
Once unity is set up, it will find the dependencies and supply them to the program at runtime. Therefore, if I need a ICustomerRepository for the service layer to work properly, Unity will give the Service layer a CustomerRepository instance. Since CustomerRepository inherits from ICustomerRepository Unity is able to make this link (once you've set it up) and supply the proper instance.
The Setup & Code
The easiest way to see HOW Unity works is to get into the code. My recommendation is to download the sample below, fire it up in Visual Studio and set some break points to see how the code is interacting. Seeing is believing!
Before Unity can supply your application types at runtime, you have to tell Unity WHAT you want it to supply and where to find it. This can be done multiple ways as described here. Today we will go over manual configuration inside of the console app, and xml configuration.
The manual configuration that I've utilized here utilizes the fluent interface of the container.
Explanation of code: Here we are telling Unity to register a type. We're saying "If someone requests ICustomerRepository, give them an instance of CustomerRepository. If someone requests ICustomerDTOMapper, then give them an instance of CustomerDTOMapper. ..." and so on.
Using the Container From Manual Configuration
After you've set up the types of objects the container should resolve, you can then ask the container for a instance of "ICustomerService" and then invoke a method call on it. At this very point in time Unity will give you the CustomerService, and then when the customer service needs a repository Unity will then give it a instance of CustomerRepository, etc. At this point in time, everything is mapped for you behind the scenes. The only thing you have to do is ask for the first object and Unity will walk the dependency graph and fill in the blanks for you (if as long as you've given Unity the proper types it needs).
Here's how to do this in the code:
XML configuration utilizes an external XML file (app.config/web.config) to create its dependency graph. This allows for a lot more freedom in what you would like to do with your app. If you're not happy with a certain version of "ICustomerRepository" you can create a new one, drop the DLL in the bin folder and change this config file to point to the new one and you're done. No recompiling!
In this implementation I'm using the app.config file because this is a Console App for example purposes. The full schema for XML configuration can be found here on the MSDN.
To utilize the XML configuration you'll need to utilize a custom config section. You can do this by placing this code into your config section of your app.config file:
Next, you'll need to add the container and type definition as shown below (this is just a snippet, full code is included at the bottom of the post):
The container gets its types from the config file at runtime.
Each type is declared in the config file as the "type" of object to find and the "mapTo" defines which object to return when the "type" is requested.
The type definitions are declared as type, assembly.
Using the Container From XML Configuration
To force Unity to use the XML Configuration you have to perform few extra set up steps in the application code as shown below. Essentially you're telling Unity that it's configuration/mappings are stored in a config file. The config section configures the container for you, as shown below.
To have Unity resolve an instance, its the same as the manual configuration option above. Here is the same image from above that displays how to do this:
Overall, using Unity as quite simple for this example. The docs on MSDN were pretty good, however I didn't really like the examples that were contained with the download because they did not show you how to utilize XML configuration as I wanted to. It didn't take but a few minutes to figure out what I needed to do. I think Unity is a decent solution at this time. I plan to investigate further into the depths of Unity to see if it may possibly be an alternative for my favorite container tool, Windsor Container.
Download The Code For This Post