Зарегистрируйте открытые общие типы для всех типов, реализующих некоторый интерфейс с structureMap
-
25-10-2019 - |
Вопрос
Я хочу зарегистрировать все мои типы реализации IManager
чтобы их можно было использовать в качестве типа T
для общего Lazy<T>
учебный класс.
Например:
public TetraRadioPropertyUpdater(Lazy<IRadioManager> lazyRadioManager)
Я использую самостоятельный сканер, потому что мои конкретные типы и интерфейсы являются внутренними, и поэтому я не могу использовать встроенный механизм сканирования структуры.
В первом заявлении о регистрации цикла все мои IManager
типы как For<IRadioManager>().Singleton().Use<RadioManager>()
Кроме того, я хочу, чтобы они были зарегистрированы, чтобы их можно было использовать в качестве общего типа для Lazy<T>
как For<Lazy<IRadioManager>().Use<Lazy<RadioManger>>()
InterfaceScanner<IManager> interfaceScanner = new InterfaceScanner<IManager>();
// managerMapping looks like:
// { IRadioManager, RadioManager }
// { ICallManager, CallManager }
// .. more manager interface to plugin type pairs
foreach (KeyValuePair<Type, Type> managerMapping in interfaceScanner.Process())
{
// the key is the plugin type, value is the concrete type
For(managerMapping.Key).Singleton().Use(managerMapping.Value);
// something like this.. ?
For(typeof(Lazy<>)).Singleton().Use(c => new Lazy(() => c.GetInstance(managerMapping.Value)));
}
Это возможно? Как мне нужно настроить его для structureMap?
Решение
ОБНОВИТЬ: StructureMap V3 реализует это из коробки, поэтому этот трюк больше не нужен.
Вы можете явно зарегистрировать классы, как это:
container = new Container(x =>
{
x.Scan(y =>
{
y.TheCallingAssembly();
y.WithDefaultConventions();
});
x.For<Lazy<IFoo>>().Use(y => new Lazy<IFoo>(y.GetInstance<Foo>));
x.For<Lazy<IBar>>().Use(y => new Lazy<IBar>(y.GetInstance<Bar>));
x.For<Lazy<IBaz>>().Use(y => new Lazy<IBaz>(y.GetInstance<Baz>));
});
Было бы лучше, если бы это было сделано автоматически. В идеале было бы неплохо следующего синтаксиса.
x.For(typeof(Lazy<>)).Use(typeof(Lazy<>));
К сожалению, во время выполнения, StructureMap попытается найти «самый жадный» конструктор для Lazy<T>
и успокоиться public Lazy(Func<T> valueFactory, bool isThreadSafe)
. Анкет Так как он не знает, что делать с логическим параметром isthreadsafe. Это сделает исключение. Вы можете явно сказать StructureMap, какое значение использовать как это.
x.For(typeof(Lazy<>)).Use(typeof(Lazy<>))
.CtorDependency<bool>("isThreadSafe").Is(true);
Который остановит исключения и использует значение «true» для параметра iSTHreadSafe. Документация для ленивых утверждает, что режим безопасности потока по умолчанию Lazy(Func<T> valueFactory)
Конструктор есть LazyThreadSafetyMode.ExecutionAndPublication
, что также является тем, что вы получаете, перенесив верно в параметр isThreadSafe вышеуказанного, поэтому мы получим то же поведение, что и на конструктор, который мы на самом деле хотели использовать в первую очередь (например, Lazy(Func<T> valueFactory)
) Вы можете прочитать о ленивом классе более подробно здесь.
Я понимаю, что это напрямую не отвечает на ваш вопрос в отношении класса пользовательского сканера, но это должно дать вам хорошее начало, я надеюсь.