Search code examples
c#.netdependency-injectionunity-container

Unity resolving constructor with ICollection<IMyInterface> dependency


I'm programming a rule engine. I have an interface IRule which many rules implement. Additionally, I have a RuleExecutor which get an IEnumerable<IRule> dependency injected.

I want Unity to inject an IEnumerable<IRule> with all bound implementations, but it doesn't work unfortunately.

This is my configuration:

container.RegisterType<IRule, RuleA>("a");
container.RegisterType<IRule, RuleB>("b");
container.RegisterType<IRule, RuleC>("c");
container.RegisterType<IRule, RuleD>("d");
container.RegisterType<IRule, RuleE>("e");
container.RegisterCollection<IRule>();

container.RegisterType<IRuleExecutor, RuleExecutor>(new InjectionConstructor(typeof(IEnumerable<IRule>)));

RegisterCollection is this:

public static class UnityExtensions
{
    public static void RegisterCollection<T>(this IUnityContainer container) where T : class
    {
        container.RegisterType<IEnumerable<T>>(new InjectionFactory(c => c.ResolveAll<T>()));
    }
}

I get following exception message when resolving:

RuleExecutor does not have a constructor that takes the parameters ().

How is this possible with Unity?


Solution

  • Unity will inject all named instances into an IEnumerable<T> automatically. Here is a working example.

    using System.Collections.Generic;
    using Unity;
    
    class Program
    {
        static void Main(string[] args)
        {
            var container = new UnityContainer();
    
            container.RegisterType<IRule, RuleA>("a");
            container.RegisterType<IRule, RuleB>("b");
            container.RegisterType<IRule, RuleC>("c");
            container.RegisterType<IRule, RuleD>("d");
            container.RegisterType<IRule, RuleE>("e");
            container.RegisterType<IRuleExecutor, RuleExecutor>();
    
            var executor = container.Resolve<IRuleExecutor>();
        }
    }
    
    public interface IRule { }
    public class RuleA : IRule { }
    public class RuleB : IRule { }
    public class RuleC : IRule { }
    public class RuleD : IRule { }
    public class RuleE : IRule { }
    
    public interface IRuleExecutor { }
    public class RuleExecutor : IRuleExecutor
    {
        public RuleExecutor(IEnumerable<IRule> rules)
        {
            // Rules RuleA through RuleE are injected here...
        }
    }