Search code examples
c#autofaccovariance

Autofac - resolving less specific covariant implementations


I am using Autofac. Let's say I have an covariant interface

interface IOptionFactory<out T> where T : IOption

and specific implementations

class Option1Factory : IOptionFactory<Option1>
class Option2Factory : IOptionFactory<Option2>

I register them as

container.RegisterType<Option1Factory>.As<IOptionFactory<Option1>>();
container.RegisterType<Option2Factory>.As<IOptionFactory<Option2>>();

Is there a way, how to resolve all implementations of IOptionFactory? Because this is covariant, this should be legal in C# (am I right?). Something like:

var factories = container.Resolve<IEnumerable<IOptionFactory<IOption>>>();

Solution

  • The best solution is to wrap your code in a Reporting class with a private IEnumerable property of IOptionFactory<IOption>.

    private class Reporting
    {
        private IEnumerable<IOptionFactory<IOption>> _allOptionsFactories;
    
        public Reporting(IEnumerable<IOptionFactory<IOption>> allOptionsFactories)
        {
            if (allOptionsFactories == null)
            {
                throw new ArgumentNullException("Parameter:" + nameof(allOptionsFactories));
            }
            this._allOptionsFactories = allOptionsFactories;
        }
    
        public void Report()
        {
            foreach (var optionsFactories in _allOptionsFactories)
            {
                Console.WriteLine(optionsFactories.GetType());
            }
        }
    }
    

    And then you can register and use them with:

    [TestMethod]
    public void PassingParametersToRegister_NamedParameter()
    {
        ContainerBuilder builder = new ContainerBuilder();
    
        builder.RegisterType<IOption1Factory1<SomeOption>>().As<IOptionFactory<IOption>>();
        builder.RegisterType<IOption1Factory2<SomeOption>>().As<IOptionFactory<IOption>>();
        builder.RegisterType<Reporting>();
    
        using (var container = builder.Build())
        {
            container.Resolve<Reporting>().Report();
        }
    
        //OUTPUT:
    
        //Enumerations + IOption1Factory1`1[Enumerations + SomeOption]
        //Enumerations + IOption1Factory2`1[Enumerations + SomeOption]
    }
    

    Here is the entire code in my github