开发者

Autofac register and resolve types implementing a generic interace

Im not sure how to state this question, because im not sure where the problem lies. I think its a genetric covariance issue, but the solution might be found somewhere else, maybe in the way the interfaces are designed, or in how the implementations are registered.

Anyway, the sample is trying to register all types implementing a generic interface, then later resolve the type using the type of the generic. Then trying to cast this type to its base type to be able to call a method on that implementation.

Its now failing when trying to cast. As an example, the first line of code fails to compile. When removed, the program fails on the line trying to cast the implementation.

class Program
{
    private static IContainer _container;

    static void Main(string[] args)
    {
        // Is this the problem?
        IHandler<IConfiguration> test = new MyHandler();

        // setup ioc
        var builder = new ContainerBuilder();
        builder.RegisterAssemblyTypes(typeof(Program).Assembly)
            //.Where(t => typeof(IHandler<IConfiguration>).IsAssignableFrom(t));
            .Where(t => t.GetInterfaces()
                .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IHandler<>))
                .Any()
                )
            .As(t => t.GetInterfaces()
                .Where(i => i.GetGenericTypeDefinition() == typeof(IHandler<>))
                .Single()
            );
        _container = builder.Build();

        // get开发者_运维技巧 my configuration impl
        var configuration = new MyConfiguration();

        // resolve handler for the configuration
        var configurationType = configuration.GetType();
        var handlerGenericType = typeof(IHandler<>);
        var handlerType = handlerGenericType.MakeGenericType(configurationType);
        var handler = _container.Resolve(handlerType);
        var typedHandler = (IHandler<IConfiguration>) handler;

        // handle it!
        typedHandler.Handle(configuration);
    }
}

public interface IConfiguration
{
}

public interface IHandler<T> where T : IConfiguration
{
    void Handle(T myConfiguration);
}

public class MyConfiguration : IConfiguration
{
}

public class MyHandler : IHandler<MyConfiguration>
{
    public void Handle(MyConfiguration myConfiguration)
    {
        Console.WriteLine("Handling my stuff...");
    }
}


There is no way this is going to work.
Here is the reason why:
An IHandler<IConfiguration> requires an IConfiguration as parameter to Handle.
If your first line would be valid, the following would compile:

MyOtherConfiguration config = new MyOtherConfiguration();
IHandler<IConfiguration> test = new MyHandler();
test.Handle(config);

Obviously, this is not correct, because MyHandler.Handle wants a MyConfiguration or derived type.

Using contra-variance as described in my earlier version of this answer would allow you to do the following:

IHandler<MyDerivedConfiguration> test = new MyHandler();

with MyDerivedConfiguration being derived from MyConfiguration.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜