Normally we have some code that is common for many (if not all) derived classes. An example would be a generic repository (where I could have a generic Add, Remove, Count, Max, Load etc, or a generic model (example, a common business rule to get a unique value for a new entity based on property type, or a generic save method, etc).
Now, if I were to make a Generic model that accepts Generic repository, it could look ilke:
GenericModel<TEntity> : IGenericModel<TEntity>
{
internal GenericModel(IRepository<TEntity> genericRepository)
{
}
protected IRepository<TEntity> Repository {get; }
}
Now I need a specific model with a specific repository:
class ActivityModel : GenericModel<Activity>
{
protected ActivityModel(IActivityRepository activityRepository)
}
where
class ActivityRepository : GenericRepository<Activity>, IActivityRepository { }
That means that in ActivityModel I need to cast Repository property to IActivityRepository anytime I need to use IActivityRepository specific methods, or I can declare a new property in ActivityModel
private new IActivityRepository Repository {get { return base.Repository; } }
to hide the base.Repository property, but I am not sure whether I am doing something wrong by using this approach.
Another approach would be to add another generic paramteter
class GenericModel<TEntity, TRepository> where TRepository : IRepository<TEntity>
but I am not sure if this is also a correct approach.
So any thoughts on how to handle generic and specific implementations?
1 Answer 1
It's a general aspect of inheritance that you can't remove stuff.
In your specific example you could just ignore the protected repository, but it would potentially break further inheritance, or at least confuse it.
A simple solution would be just not to inherit from GenericModel at all, but I suppose we can assume GenericModel has some other public functionality that you do want to use.
The general answer is to: 'Prefer composition over inheritance', avoid the GenericModel completely and have a private IRepository where required. Then you can simply switch out to a specific repository in classes that use it.
eg:
public class ActivityModel : IGenericFunctionality
{
public ActivityModel(
IActivityRepository activityRepository,
IGenericFunctionalityProvider gfp
)
{
this.gfp = gfp;
this.activityRepository = activityRepository;
}
public void GenericFunctionality()
{
this.gfp.GenericFunctionality();
}
}
-
I do not understant the benefit of such approach. My understanding is that composition is used when something is not requiring all functionality from anotehr super class, so composition is required to hide all that uncecessary functionality. In my case, IActivityRepository needs all the methods from IRepository, so why would I need to use composition? Does it mean that, in case where I inject an inteface of some base tope, and then I need to have another super class, with injected inteface of another super class, in that case I never use inheritance?Goran– Goran2018年07月17日 14:36:22 +00:00Commented Jul 17, 2018 at 14:36
Explore related questions
See similar questions with these tags.
IRepostory
, however it being exposed in model, and having specific interfaces makes wonder what is the intent. If you want the model to use the repository, then it is a dependency, and probably not one you want to expose. Ok, you have your reasons... I see no problem in having a more specific type as constructor parameter to inject the dependency. However, adding it to the model interface brings trouble. Aside from that... No, the model does not need to know from where the data comes from.