I have been working on removing a lot of code duplication from my application, specifically around my models. Several models also have a collection variant that is an IEnumerable of the model type. Previously all of the collection variants were individual implementations but I was able to combine the majority of their code down into a ModelCollection base class.
Now on top of these collection models are additional models with paging values, that all have the exact same properties and so I would like to also collapse these into a base class. The problem I'm running into is that .NET does not support multiple inheritance and because each of the ModelCollection implementations still need to be explicitly implemented, as most have some special logic, a simple Generic chain won't solve the problem either.
The ModelCollection Base class:
public abstract class ModelCollection<TModel> : IEnumerable<T>, IModel where TModel : IPersistableModel
{
protected readonly List<TModel> Models;
protected ModelCollection()
{
Models = new List<TModel>();
}
protected ModelCollection(params TModel[] models)
: this((IEnumerable<TModel>)models)
{
}
protected ModelCollection(IEnumerable<TModel> models)
: this()
{
models.ForEach(Models.Add);
}
public virtual int Count
{
get { return Models.Count; }
}
public virtual IEnumerator<TModel> GetEnumerator()
{
return Models.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public virtual void Add(TModel model)
{
Models.Add(model);
}
public virtual void Accept(Breadcrumb breadcrumb, IModelVisitor visitor)
{
foreach (var model in this)
{
model.Accept(breadcrumb.Attach("Item"), visitor);
}
visitor.Visit(breadcrumb, this);
}
public bool IsSynchronized { get; set; }
}
A sample of a PagedCollection:
public class PagedNoteCollection : NoteCollection
{
public PagedNoteCollection(params Note[] notes)
: base(notes)
{
}
public int CurrentPage { get; set; }
public int TotalPages { get; set; }
public int TotalNotesCount { get; set; }
}
The IModel interface for reference:
public interface IModel
{
void Accept(Breadcrumb breadcrumb, IModelVisitor visitor);
}