I´m creating an API in .NET using Carter. I have this Module Defined:
public class VariationsModule : EntityModule<Variation>
{
public VariationsModule()
{
this.MainRoute = "api/variations";
}
public override Task AddEntity(HttpContext context, [FromBody] Variation entity, [FromServices] IEntityService<Variation> entityService)
{
return base.AddEntity(context, entity, entityService);
}
}
Where EntityModule
contains common methods to all the entities that I´m planning to add and is defined like:
public abstract class EntityModule<TEntity> : ModuleBase where TEntity : Entity
It also provides the basic endpoints for the modules:
public override void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet(this.MainRoute, this.GetEntities);
app.MapPost(this.MainRoute, this.AddEntity);
app.MapGet(this.MainRoute + "/{id:guid}", this.GetEntity);
app.MapPut(this.MainRoute + "/{id:guid}", this.UpdateEntity);
app.MapDelete(this.MainRoute + "/{id:guid}", this.DeleteEntity);
}
Module base is the implementation of the ICarterModule
interface
The problem basically is that the IEntityService<Variation>
in the VariationsModule
is null so it's not correctly injected.
This is the definition of the Variations Service
:
public class VariationsService : EntityService<Variation>, IVariationsService
IVariationsService
inherits from IEntityService<Variation>
:
public interface IVariationsService : IEntityService<Variation>
Where EntityService<T>
is:
public abstract class EntityService<TEntity> : IEntityService<TEntity> where TEntity : Entity
And then the Service is added in the DI Container like:
builder.Services.AddScoped<IVariationsService, VariationsService>();
Am I missing something? First why do I need to specify [FromServices]
in the Add method? Secondly how can I fix this problem? Might be an architectural problem?
builder.Services.AddScoped<IVariationsService, VariationsService>();
will not register IEntityService<Variation>
it will only register IVariationsService
. One approach is to scrap VariationsService
with interface completely and just register the open generic (if EntityService
is not abstract and it's implementation is satisfactory):
builder.Services.AddScoped(typeof(IEntityService<>), typeof(EntityService<>));
If you want specific registration then you will need to register it:
builder.Services.AddScoped<IEntityService<Variation>, VariationsService>();
If you need it by both interfaces then:
builder.Services.AddScoped<IVariationsService, VariationsService>();
builder.Services.AddScoped<IEntityService<Variation>>(sp => sp.GetRequiredService<VariationsService>());