Настройка стиля жизни предметов коллекции при регистрации в Simple Injector - PullRequest
1 голос
/ 20 мая 2019

Кажется, что Container.Collection.Register не имеет перегрузки, которая принимает Lifestyle.Все обнаруженные реализации будут зарегистрированы по умолчанию Lifestyle.Что является причиной отсутствия такой перегрузки?

Каков предпочтительный способ добавления коллекции, где все элементы должны иметь Lifestyle, который не является образом жизни по умолчанию?

1 Ответ

3 голосов
/ 20 мая 2019

Какова причина отсутствия такой перегрузки?

Прежде всего, потому что, (как сказал Эрик Липперт :

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

Во-вторых, перегрузки Collection.Register, которые принимают список Type экземпляров (например, Collection.Register<TService>(params Type[])), принимают список как реализаций, так и абстракций. Предоставление Lifestyle для абстракций не имеет большого смысла и даже сбивает с толку.

Чтобы понять, почему Simple Injector позволяет предоставлять абстракции, взгляните на следующую регистрацию:

container.Collection.Register<ILogger>(
    typeof(ILogger),
    typeof(ISpecialLogger),
    typeof(SqlLogger));

container.Register<ILogger, DefaultLogger>(Lifestyle.Scoped);
container.Register<ISpecialLogger, SpecialLogger>(Lifestyle.Singleton);

В этом примере регистрируется коллекция регистраторов, где два из предоставленных типов являются абстракциями. Идея, позволяющая предоставлять абстракции, заключается в том, что вы можете указать им другие регистрации. Это именно то, что делает предыдущий пример. При разрешении коллекции регистраторов она будет состоять из Scoped DefaultLogger, Singleton SpecialLogger и Transient SqlLogger.

.

Теперь рассмотрим гипотетическую новую Collection.Register перегрузку, которая принимает Lifestyle:

container.Collection.Register<ILogger>(new[]
    {
        typeof(ILogger),
        typeof(ISpecialLogger),
        typeof(SqlLogger)
    },
    Lifestyle.Transient);

container.Register<ILogger, DefaultLogger>(Lifestyle.Scoped);
container.Register<ISpecialLogger, SpecialLogger>(Lifestyle.Singleton);

Что означает, что все элементы Transient, тогда как два элемента указывают на регистрацию разных стилей жизни?

Мы не нашли хорошего API, который бы решал эти проблемы (пока), поэтому у контейнера отсутствует такая перегрузка.

Каков предпочтительный способ добавления коллекции, где все элементы должны иметь стиль жизни, который не является образом жизни по умолчанию?

Есть несколько способов сделать это.

Вариант 1: зарегистрировать элемент явно

Коллекции, зарегистрированные в Simple Injector, используют запасной механизм для определения своего образа жизни. Это делается путем проверки, существует ли конкретная регистрация для элемента коллекции. Например:

container.Collection.Register<ILogger>(typeof(SqlLogger), typeof(FileLogger));

// Ensures that SqlLogger is a Singleton when part of the IEnumerable<ILogger>.
container.Register<SqlLogger>(Lifestyle.Singleton);

Когда IEnumerable<ILogger> впервые разрешается с помощью простого инжектора, для каждого элемента он будет (в следующем порядке):

  • Попробуйте получить явно зарегистрированную конкретную регистрацию (в примере: Register<SqlLogger>
  • Попробуйте получить эту регистрацию, используя разрешение незарегистрированного типа
  • Попробуйте создать саму регистрацию при использовании настроенного Container.Options.LifestyleSelectionBehavior (по умолчанию Transient).

Вариант 2. Использование перегрузки Register (Type, IEnumerable )

Вместо предоставления списка типов или сборок для Collection.Register, вы также можете предоставить список Registration экземпляров. A Registration описывает создание определенного компонента для определенного образа жизни, и этот класс используется Simple Injection для внутреннего использования, когда вы звоните Container.Register или Container.Collection.Register. Но вы также можете создавать Registration экземпляры вручную и передавать их на перегрузку Collection.Register следующим образом:

// Load the list of types without registering them
Type[] types = container.GetTypesToRegister<ILogger>(assemblies);

// Register them using the overload that takes in a list of Registrations
container.Collection.Register<ILogger>(
    from type in types
    select Lifestyle.Transient.CreateRegistration(type, container));

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

Вариант 3: переопределить стиль жизни, выбор поведения

Если регистрация не может быть найдена, Collection.Register сама регистрируется в последнюю минуту, используя настроенный LifestyleSelectionBehavior. Поведение выбора по умолчанию всегда возвращает Lifestyle.Transient, но это поведение можно изменить. Например:

class CustomLifestyleSelectionBehavior : ILifestyleSelectionBehavior
{
    public Lifestyle SelectLifestyle(Type implementationType) =>
        implementationType == typeof(SqlLogger)
            ? Lifestyle.Singleton
            : Lifestyle.Transient;
}

Эта реализация, если, очевидно, немного наивна, но показывает концепцию. Вы можете переопределить поведение по умолчанию следующим образом:

container.Options.LifestyleSelectionBehavior =
    new CustomLifestyleSelectionBehavior();

Вариант 4: Добавить

Рядом с Collection.Register, который позволяет регистрировать все элементы за один раз, вы можете использовать методы Collection.Append. Они позволяют поочередно регистрировать элементы коллекции:

container.Collection.Append<ILogger, SqlLogger>(Lifestyle.Singleton);
container.Collection.Append<ILogger, FileLogger>(Lifestyle.Transient);

Доступны также неуниверсальные перегрузки, которые упрощают автоматическую регистрацию этих типов, например, при возврате с использованием Container.GetTypesToRegister.

Это ваши основные опции в Simple Injector v4.6. Мы могли бы решить добавить удобную перегрузку Collection.Register<T>(IEnumerable<Type>, Lifestyle) в будущем, так как пропуск этой перегрузки время от времени вызывает некоторую путаницу.

...