I create BaseService
with common functions for all entities which inherit the base object, public class Committee : BaseObject
:
public interface IBaseService<T> where T : BaseObject
{
}
public class BaseService<T> : IBaseService<T> where T : BaseObject
{
}
injection:
services.AddScoped(typeof(IBaseService<>), typeof(BaseService<>));
then I use it like this:
readonly IBaseService<Committee> _committeeService;
But for some entities, which also inherits the base object public class Evaluation : BaseObject
, I need a service, for each, with some extra business logic. So, I create a specific service which inherits base service:
public interface IEvaluationService<T> : IBaseService<T> where T : Evaluation
{
}
public class EvaluationService<T> : BaseService<Evaluation>, IEvaluationService<Evaluation>
{
}
injection:
services.AddScoped(typeof(IEvaluationService<>), typeof(EvaluationService<>));
and usage is like this:
readonly IEvaluationService<Evaluation> _evaluationService;
This code works just fine. But I'm wondering, why I have to pass <Evaluation>
when I use IEvaluationService<Evaluation>
. Why cannot I use it just like this:
readonly IEvaluationService _evaluationService;
???
The entity Evaluation
is already passed in the IEvaluationService
definition.
Why do I need to pass it again in usage?
Is there a way to simplify the usage of this service to be just readonly IEvaluationService _evaluationService;
?
The interface is declared with a type parameter T
:
public interface IEvaluationService<T> : IBaseService<T> where T : Evaluation
{
}
That type parameter is not optional. While the T
is constrained to Evaluation
, this only means that T
may be Evaluation
or any subtype of Evaluation
.
While IEvaluationService<Evaluation>
is certainly valid, so would IEvaluationService<SubEvaluation>
be, if SubEvaluation : Evaluation
.
Thus, when you've declared the interface like that, you have to state which T
you're interested in.
If you only ever want to support Evaluation
, and no subtypes of it, you could have declared the interface like this:
public interface IEvaluationService : IBaseService<Evaluation>
{
// More members here..?
}
That would enable you to use it as IEvaluationService
, because that type has no open generics.