Остановить Autofac от подачи IEnumerable <> - PullRequest
0 голосов
/ 20 декабря 2018

Я ищу способ запретить Autofac автоматически заполнять IEnumerable<> в моем конструкторе.

Например, у меня есть класс School со следующими конструкторами

public School(string name) {...}
public School(string name, IEnumerable<IStudent> students) {...}

Вы можете использовать первый конструктор для создания объекта School, а затем использовать метод AddStudent для добавления учащихся в школу.

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

Если я создаю Func<string, ISchool> schoolFactory, затем вызываю schoolFactory.Invoke("Test"), Autofac будет использовать второй конструктор и автоматически создаст новый объект Student.

Интерфейс IStudent и классы Student зарегистрированы в Autofacи класс Student имеет конструктор по умолчанию.По умолчанию используется конструктор, потому что он используется в нашем пользовательском интерфейсе, когда пользователь добавляет нового студента.Новый Студент создается с пустым именем, и пользователь может ввести имя после создания объекта Студент.

Я попробовал следующее ...

  1. Удалитьконструктор по умолчанию от Student.Это работает, но это означает, что я должен использовать другой конструктор и передать в string.Empty для имени студента.Основная проблема заключается в том, что у нас есть некоторый другой общий код для создания новых объектов, который требует от наших классов конструкторов по умолчанию.Это также не решение для всех наших классов.

  2. Измените IEnumerable<IStudent> на List<IStudent>.Это работает, и это то, что я начал делать в нашем коде, но затем оно заставляет использовать List <> вместо универсального IEnumerable<>.Это просто менее гибко.

  3. Создайте Func<string, IEnumerable<IStudent>, ISchool> schoolFactory и используйте schoolFactory.Invoke("Test", Enumerable.Empty<IStudent>).Это тоже работает.Это больше кода, но я думаю, что это более явно.

Есть ли общий способ, которым я могу помешать Autofac автоматически заполнить IEnumerable?

1 Ответ

0 голосов
/ 20 декабря 2018

Хороший вопрос.Короткий ответ: я думаю, что это невозможно.Я не очень люблю говорить «нет», когда дело доходит до разработки программного обеспечения, поэтому вот более подробное объяснение:

То, что вы видите здесь, это так называемый «тип неявных отношений» в Autofac.В частности, тот, который поддерживает разрешение коллекций .Они реализованы в Autofac через регистрационные источники .Источник регистрации - это способ динамической обработки регистраций на основе заданных критериев (в данном случае аспект сбора типа).Вы можете проверить эти источники в своем контейнере в свойстве container.ComponentRegistry.Sources;последний должен быть ответственным за это.Таким образом, чтобы отключить эту функцию, вы должны иметь возможность каким-то образом удалить этот источник регистрации из вашего контейнера, но здесь есть одна загвоздка: это свойство имеет тип IEnumerable<IRegistrationSource>, что означает, что оно доступно только для чтения и не предназначено для (хотя это и массив во время выполнения).

Но если вас интересуют другие решения проблемы, я могу порекомендовать другие подходы:

  1. Вы говорите, что у вас есть пользовательский интерфейс ипо умолчанию ctor для Student, так что пользовательский интерфейс может обрабатывать этот тип.Похоже, вы позволяете вашему пользовательскому интерфейсу вмешиваться в дизайн вашей объектной модели.Я предлагаю вам попробовать реализовать некоторые архитектурные шаблоны, разработанные для разделения UI и BLL, например, MVVM или MVC.Например, в случае MVVM у вас может быть StudentViewModel для пользовательского интерфейса, который может иметь значение по умолчанию ctor, и вы можете поддерживать ученика в чистоте только с параметризованными ctor.
  2. Если это не вариант (как вы говорите, это не вариант для всех ваших классов), вы можете попытаться указать конструктор при регистрации вашего типа ( см. Документы ).В этом случае вы можете вручную зарегистрировать конструктор не-коллекции, и Autofac использует это:

    builder.RegisterType<School>().UsingConstructor(typeof(string));
    

EDIT :

Или, есливы действительно хотите полностью отключить эту функцию, я думаю, вы можете пойти на хардкор и открыть исходный код s ** t из него :) Создайте свой собственный форк, найдите файл src / Autofac / ContainerBuilder.cs и в void RegisterDefaultAdapters(IComponentRegistry componentRegistry), вы можете видеть добавленные источники регистрации по умолчанию.Просто удалите строку с надписью componentRegistry.AddRegistrationSource(new CollectionRegistrationSource()); (строка 247 в ветви разработки в файле), затем создайте свою собственную и используйте ее.Не забудьте изменить модульные тесты;)

...