Автоматическое связывание интерфейсов с помощью AutoFac - программирование
Подтвердить что ты не робот

Автоматическое связывание интерфейсов с помощью AutoFac

У меня есть некоторые классы, такие как UserQuery, CustomerQuery, реализующие интерфейсы, такие как IUserQuery, ICustomerQuery соответственно. В моей конфигурации привязки мне нужно связать каждый интерфейс с запросом соответственно:

builder.RegisterType<UserQuery>().As<IUserQuery>().InstancePerRequest();
builder.RegisterType<CustomerQuery>().As<ICustomerQuery>().InstancePerRequest();

Это работает очень хорошо, но мне было интересно, есть ли способ сделать привязку на основе соглашения вместо привязки каждой отдельной строки XXX [Query] → [I] XXX [Query].

Я использую AutoFac в качестве контейнера DI.

4b9b3361

Ответ 1

Я не опытный пользователь AutoFac. Однако после некоторого исследования успешно протестировали код ниже:

var assembly = Assembly.GetExecutingAssembly();

builder
    .RegisterAssemblyTypes(assembly)
    .AssignableTo<IQuery>()
    .AsImplementedInterfaces()
    .InstancePerRequest();

Интерфейс IQuery выше - это просто интерфейс тега, который должен быть унаследован от каждого интерфейса запроса, который у вас есть. Используя ваш пример:

Интерфейсы

IUserQuery: IQuery
ICustomerQuery: IQuery

Классы

UserQuery: IUserQuery
CustomerQuery: CustomerQuery

Ответ 2

Вам необходимо использовать функцию сканирования сборок в Autofac.

Если ваши интерфейсы или ваши реализации разделяют базовый класс (например, QueryBase) или базовый интерфейс (например, IQuery), вы можете использовать методы convince для регистрации, такие как: AssignableTo<> и т.д. см. < Ответ href= "/questions/327523/automatically-bind-interfaces-using-autofac/1569760#1569760" > gustavodidomenico.

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

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

builder.RegisterAssemblyTypes(yourAssembly)
       .Where(t => t.IsClass && t.Name.EndsWith("Query"))
       .As(t => t.GetInterfaces().Single(i => i.Name.EndsWith(t.Name)));

Он зарегистрирует все типы из данной сборки, имя которой заканчивается на "Query" с помощью соответствующего интерфейса, поэтому он зарегистрирует SomeNiceQuery с помощью интерфейса ISomeNiceQuery

Ответ 3

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

builder.RegisterAssemblyTypes(new[] { Assembly.GetAssembly(typeof(IUserQuery))})
        .Where(x=> x.IsClass && x.Name.EndsWith("Query"))
        .As(t => t.GetInterfaces().Any() ? t.GetInterfaces()[0] : t);