Регистрация нескольких именованных типов с использованием отражения в Autofac - PullRequest
0 голосов
/ 02 мая 2019

У меня есть около 100 классов репозитория, которые реализуют один и тот же интерфейс. Все они имеют общую зависимость.

Я зарегистрировал две версии этой общей зависимости с разными именами.

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

Вот как выглядит моя первоначальная регистрация:

builder.RegisterAssemblyTypes(typeof(Repository<>).Assembly)
    .WithParameter(
        new ResolvedParameter(
            (pi, ctx) => pi.ParameterType == typeof(IClientContext),
            (pi, ctx) => ctx.ResolveNamed<IClientContext>(RegistrationKeys.Published)))
    .AsImplementedInterfaces();

Так что, если я хочу зарегистрировать все те же типы во второй раз, используя другой ключ, мне нужно будет сделать что-то вроде этого:

builder.RegisterAssemblyTypes(typeof(Repository<>).Assembly)
    .WithParameter(
        new ResolvedParameter(
            (pi, ctx) => pi.ParameterType == typeof(IClientContext),
            (pi, ctx) => ctx.ResolveNamed<IClientContext>(RegistrationKeys.Unpublished)))
    .Named(RegistrationKeys.Unpublished)
    .AsImplementedInterfaces();

Однако это не сработает, потому что метод Named требует, чтобы тип регистрации был указан, но он должен быть динамическим на основе массива разрешенных типов из вызова RegisterAssemblyTypes.

Как я могу сделать это без необходимости добавлять сотни строк кода в мое приложение?

1 Ответ

1 голос
/ 03 мая 2019

Вы можете написать собственный метод расширения для достижения этой цели.

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

builder.RegisterAssemblyTypes(typeof(AComponent).GetTypeInfo().Assembly)
       .Named(t => t.Name, typeof(object));

Эта функция принимает Type, зарегистрированную в сборке, и использует этот тип для генерации имени в службе. К сожалению, эта перегрузка также принимает в качестве типа сервиса только определенный фиксированный тип, так что это регистрирует все как Named<object>(...), что не то, что вам нужно.

НО!

Если вы посмотрите, как это реализовано ...

public static IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle>
  Named<TLimit, TScanningActivatorData, TRegistrationStyle>(
    this IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle> registration,
    Func<Type, string> serviceNameMapping,
    Type serviceType)
  where TScanningActivatorData : ScanningActivatorData
{
  return registration.As(t => new KeyedService(serviceNameMapping(t), serviceType));
}

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

public static IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle>
  NamedSelf<TLimit, TScanningActivatorData, TRegistrationStyle>(
    this IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle> registration,
    Func<Type, string> serviceNameMapping)
  where TScanningActivatorData : ScanningActivatorData
{
  return registration.As(t => new KeyedService(serviceNameMapping(t), t));
}

Теперь используйте ваше собственное расширение NamedSelf.

builder.RegisterAssemblyTypes(typeof(Repository<>).Assembly)
    .WithParameter(
        new ResolvedParameter(
            (pi, ctx) => pi.ParameterType == typeof(IClientContext),
            (pi, ctx) => ctx.ResolveNamed<IClientContext>(RegistrationKeys.Unpublished)))
    .NamedSelf(t => RegistrationKeys.Unpublished)
    .AsImplementedInterfaces();

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

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

[Отказ от ответственности: я не запускал все это через компилятор, кроме , мой разум , поэтому может быть опечатка, которая останавливает компиляцию при копировании / вставке. Вы также захотите проверить нулевые аргументы и все такое. Перейдите по ссылкам, чтобы увидеть фактический, оригинальный источник. Надеюсь, это, по крайней мере, разблокирует вас.]

...