Unity Container

Type of Injections

  • Constructor injection: Too many dependencies is an indicator of Poor Design
  • Property Setter injection
    • Only when Dependency is Optional
    • Don't use to avoid Polluting your Constructor
  • Method Call injection

Try to write Container Agnostic Code except for the root of Application where Container is configures

Injection Lifecycle

  • Register
  • Resolve
  • Dispose

Register

RegisterType: container.RegisterType<IInterface, ConcreteImplementation>();

Named Registrations

Design-Time Configuration

Load a collection of registrations from a configuration file into a container. e.g.

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace name="Tailspin.Web.Survey.Shared.Stores" />
    <container>
      <register type="ITenantStore" mapTo="TenantStore" />
    </container>
  </unity>
</configuration>

And Use LoadConfiguration extension Method to load registrations form config

IUnityContainer container = new UnityContainer();
container.LoadConfiguration();

Registration by Convention

Simplify large number off mappings with similar settings

The registration by convention feature can scan a collection of assemblies, and then create a set of mappings in a Unity container for some or all of the types it discovers in the assemblies.

You can also specify

  • Lifetime managers
  • Details of any injection parameters

Some samples:

var container = new UnityContainer();
container.RegisterTypes(
    AllClasses.FromLoadedAssemblies(),
    WithMappings.MatchingInterface,
    WithName.Default);
}

container.RegisterTypes(
  AllClasses.FromLoadedAssemblies().Where(
    t => t.Namespace == "OtherUnitySamples"),
  WithMappings.MatchingInterface,
  WithName.Default,
  WithLifetime.ContainerControlled);

Using Child Containers

Advantage over named Registrations: If type is not registered in the child container, then Unity will automatically fall back to try and resolve the type from the parent container

Can also be used to manage lifetime of object at different levels.

var childContainer = container.CreateChildContainer();

Resolve

container.Resolve<IInterface>();

ResolverOverride

pass parameters to constructor in the moment when you resolve the class.

  • ParameterOverride: A ResolverOverride class that lets you override a named parameter passed to a constructor.
  • DependencyOverride: A class that overrides the value injected whenever there is a dependency of the given type, regardless of where it appears in the object graph.
  • PropertyOverride: A ResolverOverride that lets you override the value for a specified property.

Other Features of Unity resolution

  • DependencyAttribute used for named instances
  • Automatic Factories Resolve Func<T> instead of T in the constructor. Same as differed loading.
  • Deferred Resolution Use normal Registration and use Lazy<T> for Resolving the Type var defaultLazy = container.Resolve<Lazy<MySampleObject>>();

Lifetime Management

  • RegisterType: Container instantiates a new object. Does not hold a reference to the object.
  • RegisterInstance: container manages the object and holds a reference to it for the lifetime of the container.

Available Lifetime Managers:

  • TransientLifetimeManager: Returns new instance every time Resolve or ResolveAll is called
  • ContainerControlledLifetimeManager: Singleton Instance
  • HierarchicalLifetimeManager: When there are child containers, each child resolves its own instance. Singleton for Each Container
  • PerResolveLifetimeManager: instances are reused across the build-up object graph. Recursion will return single instance.
  • ExternallyControlledLifetimeManager: Instead of Container holding the reference of the Object(as in ContainerControlledLifetimeManager) this responsibility is handed over to some other object. e.g. instance managed by ASP.net
  • PerRequestLifetimeManager: Only available in Web Applications. Each call to Resolve a type within the context of a single HTTP request will return the same instance.
  • PerThreadLifetimeManagement: returns different objects from the container for each thread.

Deferred Resolution

Use normal Registration and use Lazy<T> for Resolving the Type var defaultLazy = container.Resolve<Lazy<MySampleObject>>();

Dispose

By default Unity container does not store any reference to the object it creates.