Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Unity, How do I autoregister a generic class with a generic interface without registering EVERY type to it

I am using Unity and Unity.AutoRegistration. This line for Unity:

unityContainer.RegisterType(typeof(IAction<>), typeof(Action<>));

effectively registers every class in the project to IAction/Action:

unityContainer.RegisterType<IAction<ObjectA>, Action<ObjectA>>();
unityContainer.RegisterType<IAction<ObjectB>, Action<ObjectB>>();
unityContainer.RegisterType<IAction<ObjectC>, Action<ObjectC>>();
[...]
unityContainer.RegisterType<IAction<UnrelatedObject>, Action<UnrelatedObject>>();
[...]

But, I only want specific objects to be registered. How would I do that? My guess is to add a custom attribute decorator to the specific classes.

[ActionAtribute]
public class ObjectB
{ [...] }

And try to use Unity.AutoRegistration. This is where I am stuck at:

unityContainer.ConfigureAutoRegistration()
    .Include(If.DecoratedWith<ActionAtribute>,
             Then.Register()
             .As   ?? // I'm guessing this is where I specify
             .With ?? // IAction<match> goes to Action<match>
             )
    .ApplyAutoRegistration();
like image 645
Jaguir Avatar asked Feb 11 '10 22:02

Jaguir


1 Answers

Include method has overload that allows you to pass lambda to register your type. To achieve exactly what you want with attributes you can do like this:

        unityContainer.ConfigureAutoRegistration()
            .Include(If.DecoratedWith<ActionAtribute>,
                     (t, c) => c.RegisterType(typeof(IAction<>).MakeGenericType(t), typeof(Action<>).MakeGenericType(t)))
            .IncludeAllLoadedAssemblies()
            .ApplyAutoRegistration();

Also, first argument of Include method is Predicate, so if you don't want to use attributes but some other mechanism to define what types to include or exclude, you can do like this:

        // You may be getting these types from your config or from somewhere else
        var allowedActions = new[] {typeof(ObjectB)}; 
        unityContainer.ConfigureAutoRegistration()
            .Include(t => allowedActions.Contains(t),
                     (t, c) => c.RegisterType(typeof(IAction<>).MakeGenericType(t), typeof(Action<>).MakeGenericType(t)))
            .IncludeAllLoadedAssemblies()
            .ApplyAutoRegistration();
like image 74
Artem Govorov Avatar answered Oct 04 '22 22:10

Artem Govorov