Seeking advice on Patterns and anti-patterns for auto registration

Sep 11, 2010 at 2:26 PM

I recently tried using Unity Auto Registration because I was tired of adding a new type and forgetting to add it to the composition root.  Also, the composition root is getting to be over 40 lines of registration code and I wanted to simplify it.  So I used Unity Auto Registration to automatically regisert all types, and it works great. The only exception is that if I need to register an instance, or choose a non-default lifetime,  I must exclude it and then I can register that specific type or instance. Below is an example of my new composition root. But I'm concerned that I may be making a mistake going down this path. It seems that as long as the exceptions are few, this is great. But if the exceptions are many, I probably should just register each by hand.  Do you have any advice on when to use Unity Auto Registration, when NOT to, and how for different scenarios? I  am interested in the experience of others who have used this.       

 public static void ConfigureContainer(IUnityContainer container)
        {
            // Container cannot disambiguate data context's due to multiple long constructors
            container.RegisterInstance(new CrmModelDataContext());
            container.RegisterInstance(new RepositoryDataContext());

            container.RegisterType<
                IPerformanceReporter,
                PerformanceReporter>(new ContainerControlledLifetimeManager());//singleton

            container
                .ConfigureAutoRegistration()
                .LoadAssembliesFrom(new List<string> 
                    { "Bop.Crm.Conversion.exe", "Bop.Crm.Utility.dll" })
                .ExcludeSystemAssemblies()
                .Exclude(f => f.Name.EndsWith("DataContext"))//these must be done by hand
                .Exclude(f => f.Name.Equals("PerformanceTracker"))
                .Include(If.Any, Then.Register())
                .ApplyAutoRegistration();
        }


 


Sep 12, 2010 at 2:23 AM
Edited Sep 12, 2010 at 2:27 AM

I see part of the answer to my own question.  After I looked more closely at the tests, I see that UnityAutoRegistration allows me to specify the lifetime management like this

.Include(If.Implements<IMemberRepository>,Then.Register().UsingSingletonMode())

However, I don't see anything in the source or the tests that supports registering a known instance. Do I need to use the technique I illustrated above, where I

  1.  exclude the types that require instances, to prevent the default clause ( .Include(If.Any, Then.Register()) ) from building them?
  2. manually call container.RegisterInstance(...)

I suppose, that conceptually, the automatic aspect, with filters that can identify many types,  does not make any sense where a single instance is concerned. But I just want to verify that I'm doing things the easiest and safest way possible.

thanks

 

 


Coordinator
Sep 12, 2010 at 9:26 AM
Edited Sep 12, 2010 at 9:27 AM

Hi David,

I'm generally trying not to use 

 

.Include(If.Any, Then.Register())

 

but rather explicitly register certain conceptually related groups of types, for examples ViewModels, Controllers, Repositories, Loggers etc. This gives me better visibility in terms of seeing what I'm registering on one hand and on another hand still saves a lot of time that would take to explicitly register each and every type.

 

In regards to using various registration options, UnityAutoRegistration fluent API (Include method overload with Then.Register()... as second parameter) allows you to control most of Unity supported registration options, like: lifetime manager, selecting what type/interface to you want to register current type as, setting registration name. However, if there's something you want to do that is not supported by Then.Register() API, then you can use another Include method overload that just takes registration action as parameter (action that takes type and container and allows you to do whatever you want with them). For example, registering instances of DataContext type you've mentioned may look like:

 

.Include(t => t.Name.EndsWith("DataContext"), (t, c) => c.RegisterInstance(t, Activator.CreateInstance(t)))

To prevent .Include(If.Any, Then.Register()) from overriding your custom registration rules, you could put .Include(If.Any, Then.Register()) before other .Include calls, so last .Include call for certain type wins:

 

            container
                .ConfigureAutoRegistration()
                .ExcludeSystemAssemblies()
                .Include(If.Any, Then.Register())       // Default registration action
                .Include(                               // Custom action for DataContexts
                    t => t.Name.EndsWith("DataContext"), 
                    (t, c) => c.RegisterInstance(t, Activator.CreateInstance(t)))
                .ApplyAutoRegistration();

 

Technically it is possible to use only UnityAutoRegistration to register all your required types (with general rules, exclusions, and even 'one type' rules).

Sep 12, 2010 at 3:15 PM

Thanks for the reply. That was exactly what I was looking for.  Your experiences are very helpful. If you discover other concepts about how to best use this automatic registration, please feel free to share them. I am eager to learn from those with more experience.