ОБНОВЛЕНИЕ: 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 гласит, что режим безопасности потока конструктора Lazy(Func<T> valueFactory)
по умолчанию равен LazyThreadSafetyMode.ExecutionAndPublication
, что также можно получить, передав значение true в параметр isThreadSafe вышеприведенного конструктора, поэтому мы получим такое же поведение, как если бы мы вызвали конструктор, который мы на самом деле хотели использовать (например, Lazy(Func<T> valueFactory)
). Подробнее о классе Lazy можно прочитать здесь .
Я понимаю, что это не дает прямого ответа на ваш вопрос относительно пользовательского класса сканера, но я надеюсь, что это даст вам хорошее начало.