0

Is there a way of looping through the multiple implementations of an interface? I haven't written any DI code examples as I didn't want to limit suggestions based on a DI framework. Could be Autofac, Ninject, Unity etc. Whatever is suitable for the task.

I'll be using the ASP.Net Core but I believe the built in DI doesn't allow for multiple implementations.

So, a singular Interface.

public interface InterfaceA
{
    void MethodA();
}

Numerous classes that implement said interface and are registered.

public class Class1 : InterfaceA
{
    public void MethodA()
    {
      //Do something
    }
}

public class Class2 : InterfaceA
{
    public void MethodA()
    {
      //Do something
    }
}

Controller such as this

public TestContoller: Controller
{
    private readonly List<InterfaceA> interfaces;
    void TestController(List<InterfaceA> interfaces)
    {
        this.interfaces = interfaces;
    }

    IActionResult TestMethod()
    {
        Foreach(var implementation in interfaces)
        {
            implementation.MethodA();
        }
        return View();
    }
}
kayess
  • 3,384
  • 9
  • 28
  • 45
Rob White
  • 950
  • 1
  • 6
  • 16
  • 1
    Are you asking same question: [getting all types that implement an interface](http://stackoverflow.com/questions/26733/getting-all-types-that-implement-an-interface) ? If not, can you explain where is the problem? – Sinatr May 18 '17 at 14:58
  • I'm not really interested in the types. The code examples I've given are a hypothetical of what I want to do. I just don't know if / which DI framework would allow me to work like it. I've seen something similar in Orchard CMS which uses Autofac (I think). So maybe the question should be, is there a DI framework that would allow me to work like my hypothetical examples? If so, how would I register my implementations? – Rob White May 18 '17 at 15:26
  • Right, I miss the *"are registered"* point. So you have the collection. And why can't you iterate it? Your code doesn't compile and you didn't create instances, so I have no idea what are your intents/problems. I am not using DI frameworks though, perhaps your question is more clear when one knows one? – Sinatr May 18 '17 at 15:44
  • @Sinatra It doesn't compile, probably because I wrote it without the handy use of intellisense, my bad. With DI you don't create instances, if this is something you're unfamiliar with I'd highly recommend a look. Even with my little knowledge the benefits of using DI are quite significant. – Rob White May 18 '17 at 18:34

2 Answers2

0

Maybe something like this:

using SimpleInjector;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main (string[] args)
        {
            var container = new Container ();

            container.RegisterCollection<IMyInterface> (new[] { typeof (MyImplementationA), typeof (MyImplementationB) });

            var testController = container.GetInstance<TestController> ();

            testController.TestMethod ();

            Console.ReadKey ();
        }


        public interface IMyInterface
        {
            void DoSomething ();
        }


        public class MyImplementationA : IMyInterface
        {
            public void DoSomething () => Console.WriteLine ("A");
        }


        public class MyImplementationB : IMyInterface
        {
            public void DoSomething () => Console.WriteLine ("B");
        }


        public class TestController
        {
            private readonly IMyInterface[] instances;

            public TestController (InstancesFactory<IMyInterface> factory)
            {
                instances = factory.GetInstances ().ToArray ();
            }

            public void TestMethod ()
            {
                foreach (var instance in instances)
                {
                    instance.DoSomething ();
                }
            }
        }


        public class InstancesFactory<T> where T : class
        {
            private readonly Container container;

            public InstancesFactory (Container container)
            {
                this.container = container;
            }

            public IEnumerable<T> GetInstances ()
            {
                return container.GetAllInstances<T> ();
            }
        }
    }
}

link

apocalypse
  • 5,764
  • 9
  • 47
  • 95
  • I'm after an ASP.Net MVC Core implementation, but I'll see if I can convert. – Rob White May 18 '17 at 16:37
  • Appreciate you help @Apocalypse, I'm sure your example works but wasn't best sure how to convert. In the end I found a simpler solution – Rob White May 18 '17 at 17:51
0

I realised there was nothing special required to do what I needed if I used Autofac.

public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();

        var builder = new ContainerBuilder();

        //  builder.RegisterModule<DataModule>();
        builder.RegisterType<Class1>().As<InterfaceA>();
        builder.RegisterType<Class2>().As<InterfaceA>();

        builder.Populate(services);

        var container = builder.Build();
        return container.Resolve<IServiceProvider>();
    }

Just had to change to the method to return an IServiceProvider rather than a void. (Standard code)

This allowed me to pass in an IEnumerable to my controller constructor which I was able to loop.

Rob White
  • 950
  • 1
  • 6
  • 16