0

我一直在努力從我的應用程序中刪除大量代碼重複,特別是在我的模型周圍。幾個模型也有一個集合變體,它是模型類型的IEnumerable。以前所有的集合變體都是單獨的實現,但我能夠將他們的大部分代碼合併到一個ModelCollection基類中。如何設置一個通用分頁對象,它位於我的通用集合對象之上?

現在,在這些集合模型之上是帶有分頁值的附加模型,它們都具有完全相同的屬性,所以我也想將它們摺疊到一個基類中。我遇到的問題是,.NET不支持多繼承,因爲每個ModelCollection實現仍然需要明確實現,因爲大多數實現了一些特殊的邏輯,所以簡單的泛型鏈也不能解決問題。

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; } 
} 

一個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; } 
} 

供參考IModel接口:

public interface IModel 
{ 
    void Accept(Breadcrumb breadcrumb, IModelVisitor visitor); 
} 
+0

如果您對改善該措辭的任何建議問題,答案或標題,請不要猶豫,評論或編輯。這是一個如此複雜的問題/解決方案,我想確保一切都清晰。 – Phaeze 2014-12-19 00:31:29

回答

0

這個問題可以利用城堡可以解決

的ModelCollection基類。 DynamicProxy及其Mixins功能。

首先ModelCollection基類需要有一個接口,在這個具體的例子實施以來,僅是在IModel和IEnumerable接口的組合,只需要繼承這些接口:

public interface IModelCollection<T> : IEnumerable<T>, IModel 
{ 
} 

第二你將需要一個接口和一個實現來表示尋呼字段:

public interface IPagingDetails 
{ 
    int CurrentPage { get; set; } 
    int TotalPages { get; set; } 
    int TotalCount { get; set; } 
    bool HasPreviousPage { get; } 
    int PreviousPage { get; } 
    bool HasNextPage { get; } 
    int NextPage { get; } 
} 

public class PagingDetails : IPagingDetails 
{ 
    public int CurrentPage { get; set; } 
    public int TotalPages { get; set; } 
    public int TotalCount { get; set; } 
    public bool HasPreviousPage 
    { 
     get { return CurrentPage > 1; } 
    } 

    public int PreviousPage 
    { 
     get { return CurrentPage - 1; } 
    } 

    public bool HasNextPage 
    { 
     get { return CurrentPage < TotalPages; } 
    } 

    public int NextPage 
    { 
     get { return CurrentPage + 1;} 
    } 
} 

接着,爲了簡化一旦代理已經產生訪問各部分,(具體地,以除去要求鑄ModelCollection和PagingDetails接口之間的代理),我們需要一個空的接口來尋呼和集合接口組合:

public interface IPagedCollection<T> : IPagingDetails, IModelCollection<T> 
{} 

最後,我們需要創建與尋呼信息作爲混入代理:

public class PagedCollectionFactory 
{ 
    public static IPagedCollection<TModel> GetAsPagedCollection<TModel, TCollection>(int currentPage, int totalPages, int totalCount, TCollection page) 
     where TCollection : IModelCollection<TModel> 
     where TModel : IPersistableModel 
    { 
     var generator = new ProxyGenerator(); 
     var options = new ProxyGenerationOptions(); 
     options.AddMixinInstance(new PagingDetails { CurrentPage = currentPage, TotalPages = totalPages, TotalCount = totalCount }); 
     return (IPagedCollection<TModel>)generator.CreateClassProxyWithTarget(typeof(TCollection), new[] { typeof(IPagedCollection<TModel>) }, page, options); 
    } 
} 

現在我們可以使用代理(這是從單元測試我寫的,以確保它的工作採取):

var collection = new NoteCollection(
      new Note {Text = "note 1"}, 
      new Note {Text = "note 2"}, 
      new Note {Text = "note 3"}, 
      new Note {Text = "note 4"}); 

var pagedCollection = PagedCollectionFactory.GetAsPagedCollection<Note,NoteCollection>(1, 1, 1, collection); 

Assert.That(pagedCollection.CurrentPage, Is.EqualTo(1)); 
Assert.That(pagedCollection.ToList().Count, Is.EqualTo(4)); 
相關問題