Stable?

May 23, 2012 at 10:20 AM
Edited May 23, 2012 at 10:21 AM

Hi Chaps,

I know this Lib is being worked on a lot, but my question is, how stable is the Unity framework in it?

Also, which Libs are required for me to use the Unity integration

Cheers, Nick

Coordinator
May 23, 2012 at 10:26 AM

Hi,

that depends on the specific component you want to use. Some parts have remained stable for a while. Others change frequently as I find new problems to solve.

Are you interested in any part in particular?

Regards

Sebastian

May 23, 2012 at 10:42 AM

Thanks for the quick reply. Okay so what I am trying to do is this...

Lets say I have a marker interface called IDependency..

public interface IDependency{ }

I then have several interfaces hanging off of this...

public interface ICustomerService : IDependency { }

public interface ICustomerRepository : IDependency { }

and then have some classes too...

public class CustomerService : ICustomerService {
     public CustomerService(ICustomerRepository customerRepo){ }
}

public class SomOtherCustomerService : ICustomerService {
     public CustomerService(ICustomerRepository customerRepo){ }
}

public class NicksController : Controller {
     public NicksController(IEnumerable<ICustomerService> customerServices) { }
}

 

I have used the IDependency as a marker interface to allow me to identify all interfaces I want Unity to pickup. How do you see me wiring this up?

Coordinator
May 23, 2012 at 11:10 AM

I would drop the IDependency interface. The container can figure that out by itself. The TecX configuration engine offers support for convention-based registration of dependencies. That would make your registration code look something like this:

ConfigurationBuilder builder = new ConfigurationBuilder();
builder.Scan(s =>
    {
        s.With(new FindAllImplementationsConvention(typeof(ICustomerService)));
        s.TheCallingAssembly();
    });
builder.For<ICustomerRepository>().Use<CustomerRepository>();
builder.Extension<CollectionResolutionExtension>();
var container = new UnityContainer();
container.AddExtension(builder);
var controller = container.Resolve<NicksController>();
The FindAllImplementationsConvention will search the specified assemblies for all implementations of ICustomerService and register them under a unique name. The repository is registered manually (although it can be registered using the ImplementsIInterfaceNameConvention). The CollectionResolutionExtension teaches Unity how to resolve IEnumerable<T>. Out of the box Unity only knows about arrays.

Add the ConfigurationBuilder to the container and resolve your controller and you are done.

May 23, 2012 at 11:17 AM

Ah Fantastic. Do I just need to include the following dlls?

TecX.Common.dll
TecX.Unity.dll

Coordinator
May 23, 2012 at 11:23 AM

To use the configuration block you need

TecX.Unity.Configuration.dll

as well.

Enjoy :)

May 23, 2012 at 11:28 AM

Thanks :)

How would this work if I wanted to register stuff as a singleton?

I used the IDepenency as something to say it was per request. say I then had ISingletonDependency... how could I make it distinguish?

Coordinator
May 23, 2012 at 11:47 AM

You can write a custom convention that registers all implementations of ICustomerService as singletons. Therefor you would just need to append .AsSingleton() in the FindAllImplementationsConvention.Process() method.

Or you can set the singleton lifetime after running the convention using

builder.For<ICustomerServer>().LifetimeIs(() => new ContainerControlledLifetimeManager());

May 23, 2012 at 12:39 PM

hmm, What I am trying to avoid is people having to setup IoC stuff, I was thinking that If I used something like IDependency or ISingletonDependency this would mean people could avoid touching the IoC and its abstracted away from the developer.

Coordinator
May 23, 2012 at 12:46 PM

With those interfaces you still put the burden of the configuration of your container on the developer. In fact you make it even harder because they would now have to decide from which interface they inherit and remove the ability to switch the lifetime of their dependencies by flipping a configuration switch.

May 23, 2012 at 1:04 PM

It depends on what you are trying to achieve.

For Example, Orchard CMS uses a IDependency pattern to abstract away the IoC pattern from the developer and it works really well... But you can still create ConfigurationBuilder classes (Register in AutoFac) in your MVC areas and set your own dependencies.

also... the below does not work if I try to inject a single instance instead of a collection...

ConfigurationBuilder builder = new ConfigurationBuilder();
builder.Scan(s =>
    {
        s.With(new FindAllImplementationsConvention(typeof(ICustomerService)));
        s.TheCallingAssembly();
    });
builder.For<ICustomerRepository>().Use<CustomerRepository>();
builder.Extension<CollectionResolutionExtension>();
var container = new UnityContainer();
container.AddExtension(builder);
var controller = container.Resolve<NicksController>();

i.e. If I try to do

public class NicksController : Controller {
     public NicksController(ICustomerService customerServices) { }
}

instead of

public class NicksController : Controller {
     public NicksController(IEnumerable<ICustomerService> customerServices) { }
}

It falls over.

Coordinator
May 23, 2012 at 1:36 PM

Sure it does. How should Unity guess which implementation of ICustomerService you want injected into the controller? All implementations registered by that convention are named mappings. If you don't register a default mapping (one without a name) the call to container.Resolve() will fail, as the container cannot make an educated guess what scheme you might have had in mind. You can either change the behavior of the convention (say the first implementation it finds is registered as default mapping) or you can define which of the mappings done by the convention should be used for the constructor of the controller.

How does AutoFac solve that problem?

May 23, 2012 at 1:41 PM

Autofac uses the first one registered if you are injecting a single one, and all if you are injecting a collection. Is this what you mean?

Coordinator
May 23, 2012 at 1:55 PM

That sounds like a new problem to solve :)

I'll see what I can do about that. But that will take some time.

May 23, 2012 at 2:54 PM

Very cool!!! Will it be a tricky one to implement?

Coordinator
May 24, 2012 at 6:49 AM

Not if you know where to look for the solution.

Please see the DefaultMappingExtension (TecX.Unity in folder Mapping).

Jun 12, 2012 at 9:19 AM

Sorry forgot to get back to you. Works perfectly!!! I have a new question but will open up a new thread. Thanks Nick