2016-10-19 2 views
0

Для следующей регистрации контейнера:StructureMap разрешить все экземпляры для универсального типа во время выполнения

c.For(typeof(IHandler<bool>)).Use(typeof(BoolHandler)); 
c.For(typeof(IHandler<int>)).Use(typeof(IntHandler)); 

Я пытаюсь получить список типов во время выполнения, как так:

var test = Container.Current.Get(typeof(IHandler<>)); // doesn't work 
var test = Container.Current.GetAllInstances<IHandler<object>>(); // doesn't work 

Я получаю кол-во 0;

ответ

1

Вы не можете позвонить Get(typeof(IHandler<>)), потому что невозможно создать экземпляр открытого типа; это невозможно в CLR.

Разрешающая коллекция IHandler<object> бы только привести какие-либо элементы, либо когда вы явно зарегистрировали IHandler<object> -или- когда IHandler<T> определяется как ковариантный, то есть, используя ключевое слово out в IHandler<out T>. Не имея in или out ключевых слов на вашем интерфейсе, ваш интерфейс не является вариантом, и невозможно закрыть закрытую версию интерфейса для другой закрытой версии этого же интерфейса.

Только тогда, когда абстракция определяется как IHandler<out T> это можно назначить IHandler<string> к IHandler<object>, потому что T будет выходным аргументом и string может быть преобразован в object.

Маловероятно, что это вам полезно, поскольку у обработчиков обычно есть входной аргумент. Однако, когда абстракция определяется как IHandler<in T> (это имеет гораздо больший смысл), это означает, что вы можете назначить IHandler<object> из IHandler<string>, потому что вы можете передать строковый аргумент в IHandler<object>, но не наоборот.

Чтобы сделать это более конкретным, следующие будут компилировать:

interface IHandler<in T> { } 

var handlers = new IHandler<string>[] 
{ 
    new Handler<string>(), 
    new Handler<object>(), 
}; 

Но следующий не будет:

interface IHandler<in T> { } 

var handlers = new IHandler<object>[] 
{ 
    new Handler<string>(), 
    new Handler<object>(), 
}; 

Аналогично, следующие будут компилировать:

interface IHandler<out T> { } 

var handlers = new IHandler<object>[] 
{ 
    new Handler<string>(), 
    new Handler<object>(), 
}; 

Но следующее не будет:

interface IHandler<out T> { } 

var handlers = new IHandler<string>[] 
{ 
    new Handler<string>(), 
    new Handler<object>(), 
}; 

Поскольку это имеет место для C# и CLR вообще, для StructureMap (или любого контейнера) нет возможности обойти это. И поэтому у вас не будет никаких результатов.

+0

Perfect информация. Имеет смысл. Спасибо! – ShaneKm

Смежные вопросы