develorem
10/9/2018 - 1:17 AM

C# Register generic types in DI

Shows how to use reflection to register generic types when you have things like Bar : IFoo and you want to resolve by IFoo.

    public interface ISound { }
    public interface ISound<T> : ISound { }
    public class Moo { }
    public class Chirp { }
    public class Hiss { }
    public class Cow : ISound<Moo> { }
    public class Bird : ISound<Chirp> { }
    public class Snake : ISound<Hiss> { }
    
    [TestClass]
    public class TestAnimals
    {
    [TestMethod]
        public void Explicit()
        {
            var services = new ServiceCollection();
            services.AddTransient<ISound<Moo>, Cow>();

            var c = typeof(ISound<Chirp>);
            services.AddTransient(c, typeof(Bird));

            var h = typeof(Hiss);
            var s = typeof(ISound<>);
            var ht = s.MakeGenericType(h);
            services.AddTransient(ht, typeof(Snake));

            var provider = services.BuildServiceProvider();

            var exCommand = provider.GetService<ISound<Moo>>();
            var exPS = provider.GetService<ISound<Chirp>>();
            var exPy = provider.GetService<ISound<Hiss>>();

            Assert.IsNotNull(exPy);
        }
        
        [TestMethod]
        public void Automatic()
        {
            var services = new ServiceCollection();

            var soundType = typeof(ISound);
            var ignoreTypes = new Type[] { soundType, typeof(ISound<>) };
            var allTypes = soundType.Assembly.GetTypes() 
                .Where(x => soundType.IsAssignableFrom(x)) 
                .Where(t => !ignoreTypes.Contains(t)) 
                ;
            foreach (var type in allTypes)
            {               
                var implementedInterface = type.GetInterfaces().FirstOrDefault(x => x != soundType);
                services.AddTransient(implementedInterface, type); // Register each one as the base type
            }

            var provider = services.BuildServiceProvider();

            var exCommand = provider.GetService<ISound<Moo>>();
            var exPS = provider.GetService<ISound<Chirp>>();
            var exPy = provider.GetService<ISound<Hiss>>();

            Assert.IsNotNull(exPy);
        }
    }