Как зарегистрировать конкретный класс в универсальный интерфейс? - PullRequest
2 голосов
/ 30 июня 2019

Я пытаюсь зарегистрировать конкретный класс, который основан на универсальном классе, и этот универсальный класс основан на универсальном интерфейсе. Проблема в том, как сделать это в Castle Windsor и ASP.NET Boilerplate, чтобы мне не нужно было много кода, который регистрирует его один за другим.

public interface IService<T> where T: class ...

public class Service<T, TE, TPrimary> : IService<T> where T: class ...

public class ConcreteService : Service<SomeType, SomeType2, string> ...
public class AnotherConcreteService : Service<AnotherSomeType, AnotherSomeType2, string> ...

С такой структурой я хотел бы зарегистрировать IService<SomeType> класс ConcreteService, который реализует этот сервис. Как я мог сделать это с Виндзорским замком? Реализация по одному выглядит так:

IocManager.IocContainer.Register(Component.For(typeof(IQueryService<SomeType>))
    .ImplementedBy(typeof(ConcreteService)).Named("ConcreteTest"));

IocManager.IocContainer.Register(Component.For(typeof(IQueryService<AnotherSomeType>))
    .ImplementedBy(typeof(AnotherConcreteService)).Named("AnotherConcreteTest"));

Использование, которое я хотел бы иметь:

var test1 = IocContainer.Resolve<IQueryService<SomeType>(); // Here should be ConcreteService
var test2 = IocContainer.Resolve<IQueryService<AnotherSomeType>(); // Here should be AnotherConcreteService

При линейном подходе это работает, но как зарегистрировать все на основе IQueryService<>?

Ответы [ 2 ]

2 голосов
/ 03 июля 2019

Если ваша цель состоит в том, чтобы зарегистрировать все различные реализации обобщенного IQueryService<T> в одном выражении, вы, скорее всего, после чего-то вроде этого

container.Register(
   Classes.FromThisAssembly()
      .BasedOn(typeof(IQueryService<>))
      .WithServiceBase()
);

Я настоятельно рекомендую потратить некоторое время на документацию , в которой рассматриваются все варианты

1 голос
/ 21 июля 2019

1.IQueryService<SomeTypeDto>

Castle.MicroKernel.ComponentNotFoundException: нет компонента для поддержки службы AbpCompanyName.AbpProjectName.IGenerics.IQueryService`1 [[AbpCompanyName.AbpProjectName.SomeEntitiesAmp.App.App.App.App.App.Amp.Amp.Amp_Amp_Amp_Amp_Amp_Amp_Amp_Amp_App_Amp_App_App.Amp_D_D_W_D_P_P_P_P_P_P_P_P_P_P_P_P_P_C_T_P_C_T_P_T_P_T_P_T_P_C_TOP= 1.0.0.0, Culture = нейтральный, PublicKeyToken = null]] был найден

Чтобы зарегистрировать конкретные классы в универсальном интерфейсе, используйте .WithService.Base().

Для совместимости 1 с RegisterAssemblyByConvention, настройте уникальное имя.

public override void Initialize()
{
    var thisAssembly = ...

    IocManager.RegisterAssemblyByConvention(thisAssembly);

    IocManager.IocContainer.Register(
        Classes.FromAssembly(thisAssembly)
            .BasedOn(typeof(IQueryService<>))
            .WithService.Base()
            .Configure(configurer => configurer.Named(Guid.NewGuid().ToString())) // Add this
    );

    // ...
}

1 Если ваш конкретный класс реализует ASP.NET Boilerplate ITransientDependency, то имя по умолчанию используется длязарегистрируйте класс для .WithService.Self() внутри RegisterAssemblyByConvention.

2.IRepository<SomeType>

Castle.MicroKernel.Handlers.HandlerException: Невозможно создать компонент 'AbpCompanyName.AbpProjectName.SomeEntityService.SomeTypeService', так как он имеет зависимости, которые должны быть удовлетворены.

'AbpCompany.AbpProjectName.SomeEntityService.SomeTypeService 'ожидает следующих зависимостей:
- Служба' Abp.Domain.Repositories.IRepository`1 [[AbpCompanyName.AbpProjectName.SomeEntities.Some.Type., Culture = нейтральный, PublicKeyToken = null]] ', который не был зарегистрирован.

Для использования репозиториев ASP.NET Boilerplate определите public DbSet.

public class AbpProjectNameDbContext : ...
{
    /* Define a DbSet for each entity of the application */

    // DbSet<SomeType> SomeEntities { get; set; }     // Remove this
    public DbSet<SomeType> SomeEntities { get; set; } // Add this

    // ...
}
...