Patrick Kursawe
Patrick Kursawe

Reputation: 101

IoC container struggles with generics

I have an existing program with some plugin infrastructure that currently relies on plugin classes having parameterless constructors. I'd like to offer plugin authors the opportunity to just require some infrastructure from my program by specifying parameters for the constructor. Internally, I use some generic wrapper class to encapsulate the plugin's classes and to make them behave to the rest of my program like older pre-plugin era internal classes.

I have some placeholder here representing my infrastructure:

public interface IInfrastructure
    {

    }

    public class Infrastructure : IInfrastructure
    {

    }

Some plugin interface specification:

   public interface IPlugin
    {

    }

the plugin implementation requiring my infrastructure:

public class Plugin : IPlugin
    {
        public Plugin(IInfrastructure _)
        {

        }
    }

and my generic wrapper class expecting some plugin class

public class PluginWrapper<TImpl> where TImpl: class, IPlugin
    {
        public PluginWrapper(TImpl _)
        {
        }
    }

After registering the involved types:

            ServiceLocator.Default.RegisterType<IInfrastructure, Infrastructure>(RegistrationType.Transient);
            ServiceLocator.Default.RegisterType(typeof(Plugin),typeof(Plugin), RegistrationType.Transient);
            var wrapperType = typeof(PluginWrapper<>).MakeGenericType(typeof(Plugin));
            ServiceLocator.Default.RegisterType(wrapperType, wrapperType,RegistrationType.Transient);

I find out that I can resolve the "inner" plugin type: Assert.NotNull(ServiceLocator.Default.ResolveType<Plugin>()); but I can't resolve the "Wrapper" type. Assert.NotNull(ServiceLocator.Default.ResolveType<PluginWrapper<Plugin>>());

Am I hitting a limitation of Catel's IoC container, or am I doing something wrong?

Upvotes: 0

Views: 39

Answers (1)

Patrick Kursawe
Patrick Kursawe

Reputation: 101

When not using the generic registration method, I passed the registration type in the position of the "tag" parameter by accident.

So, changing the registration part to this version:

ServiceLocator.Default.RegisterType<IInfrastructure, Infrastructure>(RegistrationType.Transient);
ServiceLocator.Default.RegisterType(typeof(Plugin),typeof(Plugin),registrationType:RegistrationType.Transient);
var wrapperType = typeof(PluginWrapper<>).MakeGenericType(typeof(Plugin));
ServiceLocator.Default.RegisterType(wrapperType, wrapperType, registrationType:RegistrationType.Transient);

fixes the problem and everything goes as expected.

Upvotes: 0

Related Questions