Зарегистрируйте открытые общие типы для всех типов, реализующих некоторый интерфейс с structureMap

StackOverflow https://stackoverflow.com/questions/6814961

  •  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)) Вы можете прочитать о ленивом классе более подробно здесь.

Я понимаю, что это напрямую не отвечает на ваш вопрос в отношении класса пользовательского сканера, но это должно дать вам хорошее начало, я надеюсь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top