ServiceStack IOC. AutoWire (this) пытается внедрить общедоступные свойства, которые не зарегистрированы в контейнере

#dependency-injection #servicestack #inversion-of-control

#внедрение зависимостей #servicestack #инверсия управления

Вопрос:

При использовании ServiceStack и его платформы IoC / DI у меня возникает следующая проблема:

Платформа DI вводит значение null в свойство, и этот тип свойства не зарегистрирован в контейнере.

 class DependencyInjectedA : IDependencyInjectedA
{
    public DependencyInjectedB { get; set; }
}

class DependencyInjectedB 
{
    public Dictionary<DateTime, SomeClass> MyProperty { get; set; }
}
 

И в моем методе настройки:

 public override void Configure(Container container)
{
    base.Configure(); // here we have code like 'Container.AutoWire(this);'
    container.AddSingleton<IDependencyInjectedA, DependencyInjectedA>();
    container.AddSingleton<DependencyInjectedB>();
}
 

Итак, в родительском классе я делаю

 Container.AutoWire(this);
 

и причина, стоящая за вызовом AutoWire, заключается в том, что я могу заставить инфраструктуру DI вводить потомков this . У меня сложилось впечатление, что только типы, которые были зарегистрированы в контейнере, будут внедрены в зависимости, а также что они будут потомками this , но, похоже, также MyProperty DependencyInjectedB вводится in, а затем со null значением, поскольку мы не добавили Dictionary<DateTime, SomeClass> в контейнер.

Вот (несколько отредактированная) картина того, что происходит: DI вводит NULL, когда я думаю, что он не должен этого делать.

введите описание изображения здесь

Mythz на самом деле говорит об этом здесь:

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

Вопросы:

  • Как я могу тогда иметь общедоступные свойства, которые я не хочу вводить?
  • Есть ли способ внедрить только те типы, которые зарегистрированы в контейнере (.AddXXX)?

Ответ №1:

Это поведение автозапуска Funq, которое выполняет как внедрение общедоступного свойства, так и конструктора.

В частности, поведение автозапуска Funq будет вводить любые свойства, которые:

  • общедоступный
  • доступно для записи (т. Е. Имеет общедоступный установщик)
  • Не является типом значения или строкой
  • Его полное имя типа не зарегистрировано в Container.IgnorePropertyTypeFullNames коллекции

Поэтому, если вы не хотите вводить свойства, они не могут соответствовать всем вышеуказанным критериям. Если вы хотите предотвратить внедрение только одного типа свойств, вы можете зарегистрировать полное имя типа в:

 Container.IgnorePropertyTypeFullNames.Add(typeof(DependencyInjectedB).FullName);
 

В качестве альтернативы измените его так, чтобы это было не public так, иначе вам не следует использовать API-интерфейсы автозапуска Funq, содержащие это поведение, вместо этого вы бы зарегистрировали зависимость с помощью пользовательской заводской функции, например:

 container.AddSingleton<IDependencyInjectedA>(c => new DependencyInjectedA());