I try to register concrete class that is based on generic class, and this generic class is based on generic interface. The problem is how to do this in Castle Windsor and ASP.NET Boilerplate such that I don't need many code that register it one by one.
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> ...
With such structure, I would like to register to IService<SomeType>
the class ConcreteService
, which implements this service. How could I do that with Castle Windsor? Implementation one by one looks like this:
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"));
Usage that I would like to have:
var test1 = IocContainer.Resolve<IQueryService<SomeType>(); // Here should be ConcreteService
var test2 = IocContainer.Resolve<IQueryService<AnotherSomeType>(); // Here should be AnotherConcreteService
With line by line approach, it works, but how to register all based on IQueryService<>
?
IQueryService<SomeTypeDto>
Castle.MicroKernel.ComponentNotFoundException: No component for supporting the service AbpCompanyName.AbpProjectName.IGenerics.IQueryService`1[[AbpCompanyName.AbpProjectName.SomeEntitiesDto.SomeTypeDto, AbpCompanyName.AbpProjectName.Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] was found
To register concrete classes to the generic interface, use .WithService.Base()
.
For compatibility1 with RegisterAssemblyByConvention
, configure a unique name.
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 If your concrete class implements ASP.NET Boilerplate's ITransientDependency
, then the default name is used to register the class for .WithService.Self()
inside RegisterAssemblyByConvention
.
IRepository<SomeType>
Castle.MicroKernel.Handlers.HandlerException: Can't create component 'AbpCompanyName.AbpProjectName.SomeEntityService.SomeTypeService' as it has dependencies to be satisfied.
'AbpCompanyName.AbpProjectName.SomeEntityService.SomeTypeService' is waiting for the following dependencies:
- Service 'Abp.Domain.Repositories.IRepository`1[[AbpCompanyName.AbpProjectName.SomeEntities.SomeType, AbpCompanyName.AbpProjectName.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' which was not registered.
To use ASP.NET Boilerplate repositories, define a 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
// ...
}