Executing a Method on All Implementations of an Interface

Full source code available here.

Have you ever wanted to execute a method on all implementations of an interface? Say you have an interface called IGenerator and four implementations of it – GeneratorA, GeneratorB, GeneratorC, and GeneratorD.
IGenerator is very simple, it has a single Generate(string details) method.

What I don’t want to do is –

var generatorA = new GeneratorA();
var generatorB = new GeneratorB();
var generatorC = new GeneratorC();
var generatorD = new GeneratorD();

I also don’t want to do this –

List<IGenerator> generators = new List<IGenerator>() { new GeneratorA(), new GeneratorB(), new GeneratorC(), new GeneratorD() } ;
foreach (var generator in generators) 

What I want to do is find all the implementations of the interface without explicitly naming them, create instances of the implementations and call the Generate(..) method. This way I can add a GeneratorE and GeneratorF and I’ll be sure their Generate(..) methods will be called.

Finding the Implementations

This code will find all the implementations of the IGenerator interface –

var iGenerator = typeof(IGenerator);
var generatorsTypes = AppDomain.CurrentDomain.GetAssemblies() 
    .SelectMany(assembly => assembly.GetTypes())
    .Where(type => iGenerator.IsAssignableFrom(type) && type.IsClass);

On line 1 I specify the type I am going to look for.

Line 2 gets all the assemblies, line 3 gets all the types in those assemblies. Line 4 limits the type to those that implement IGenerator and are a class, checking that the type is a class is important, because without it the interface itself would be included in the result.

Activating the Implementations

At this point all we have done is find the types, we have not instantiated them, so we cannot yet call the Generate(..) methods.
But of course there is a way to do just that.

List<IGenerator> generators = new List<IGenerator>();

foreach (var generator in generatorsTypes)
    generators.Add(Activator.CreateInstance(generator) as IGenerator);

Now I have a list with instances of all the implementations of IGeneraotor.

Calling the methods

Easy –

generators.ForEach(g => g.Generate("Hi from a generator."));

That’s it, find the implementations, activate them, call the method. The end.

Full source code available here.

Why you should use IDictionary, IList, etc

When returning objects from a method try to use IList, IDictionary, etc instead of List and Dictionary. This is especially important when the method is inside a class library which you distribute.

I had to edit a method that was returning a Dictionary. Inside of which some complex work was being done to populate the dictionary.
The changes needed were going to be much easier if I could use and return a ConcurrentDictionary. See here for what I was doing.

But because the method was returning a simple Dictionary it was not as straight forward as I hoped. More work needed to be done and I had the choice of:

  1. Doing the processing in a more difficult way, not involving a ConcurrentDictionary.
  2. Moving the entries from the new ConcurrentDictionary to a simple Dictionary just before calling return.
  3. Changing the return type of the method (and the associated interface).

I went with option three, this happened to be the easiest, but it was also the best. If the code had initially been written to return IDictionary I would only have had to concern myself with required logic changes inside the method.

Here is a quick, but contrived, example of the flexibility gained by using IDictionary.

The class has a single public method which returns an IDictionary. Depending on the boolean value of getConcurrentDictionary it does its work using either as a simple Dictionary or a ConcurrentDictionary, but the caller does not need be aware of this. This gives great flexibility, the method GetDataDictionary can change its internal implementation and even the type of dictionary it returns without any negative impact on the caller.

The caller also has the flexibility to cast the IDictionary to a ConcurrentDictionary as needed.

    class GetDataWithInterfaceCollections : IGetDataWithInterfaceCollections
        public IDictionary<int, int> GetDataDictionary(int start, int end, bool getConcurrentDictionary)
            IDictionary<int, int> dictionaryToReturn;

            if (getConcurrentDictionary)
                dictionaryToReturn = GetConcurrentDictionary(start, end);
                dictionaryToReturn = GetDictionary(start, end);

            return dictionaryToReturn;

        private IDictionary<int, int> GetConcurrentDictionary(int start, int end)
            //ConcurrentDictionary offers a lot of features not available in Dictionary
            ConcurrentDictionary<int, int> dictionary = new ConcurrentDictionary<int, int>();
            for (int loop = start; loop <= end; loop++)
                dictionary.AddOrUpdate(loop, loop*10, (i, i1) => loop * 10 ); // AddOrUpdate is specific to a ConcurrentDictionary

            return dictionary;

        private IDictionary<int, int> GetDictionary(int start, int end)
            IDictionary<int, int> dictionary = new Dictionary<int, int>();
            for (int loop = start; loop <= end; loop++)
                dictionary.Add(loop, loop * 10);

            return dictionary;

Here is how to call the method shown above.

            IDictionary<int, int> concurrentDictionary = _getDataWithInterfaceCollections.GetDataDictionary(1, 10, true);

            IDictionary<int, int> simpleDictionary = _getDataWithInterfaceCollections.GetDataDictionary(11, 20, false);

            ConcurrentDictionary<int, int> explicitConcurrentDictionary = _getDataWithInterfaceCollections.GetDataDictionary(21, 30, true) as ConcurrentDictionary<int, int>; 

Using the Watch window in Visual Studio we can see more info.

Dictionary Types