Autofac регистрирует и разрешает типы, реализующие общее взаимодействие - PullRequest
1 голос
/ 08 августа 2011

Я не уверен, как сформулировать этот вопрос, потому что я не уверен, в чем проблема. Я думаю, что это проблема генетической ковариации, но решение может быть найдено где-то еще, возможно, в том, как спроектированы интерфейсы, или в том, как зарегистрированы реализации.

В любом случае образец пытается зарегистрировать все типы, реализующие универсальный интерфейс, а затем разрешает тип с использованием типа универсального. Затем попытка привести этот тип к его базовому типу, чтобы иметь возможность вызывать метод в этой реализации.

Его теперь не удается при попытке разыграть. Как пример, первая строка кода не компилируется. При удалении программа терпит неудачу в строке, пытаясь привести реализацию.

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...");
    }
}

1 Ответ

2 голосов
/ 08 августа 2011

Это не сработает.
Вот причина, по которой:
IHandler<IConfiguration> требует IConfiguration в качестве параметра Handle.
Если ваша первая строка будетдопустимо, скомпилируется следующее:

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

Очевидно, что это не правильно, потому что MyHandler.Handle хочет MyConfiguration или производный тип.

Использование противоречивости, как описано в моей предыдущей версии этого ответа, позволит вам сделать следующее:

IHandler<MyDerivedConfiguration> test = new MyHandler();

с MyDerivedConfiguration, полученным из MyConfiguration.

...