0

저는 제 응용 프로그램에서 많은 코드 중복을 제거하고 있습니다. 특히 내 모델을 중심으로. 여러 모델에는 모델 형식의 IEnumerable 인 컬렉션 변형도 있습니다. 이전에 모든 컬렉션 변형은 개별 구현 이었지만 대부분의 코드를 ModelCollection 기본 클래스에 결합 할 수있었습니다.제네릭 컬렉션 객체 위에있는 일반 페이징 객체를 어떻게 설정합니까?

이 컬렉션 모델의 맨 위에는 페이징 값이있는 추가 모델이 있으며, 모두 동일한 속성을 가지고 있으므로 기본 클래스로 축소하려고합니다. .NET에서 다중 상속을 지원하지 않으며 각 ModelCollection 구현을 명시 적으로 구현해야하기 때문에 대부분의 특수 논리가 있으므로 간단한 일반 체인으로도 문제가 해결되지 않습니다.

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

답변

0

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

다음으로, 프록시가 생성되면 다양한 부분에 액세스 간단히하기 위해, (특히하기위한 요구를 제거

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); 
    } 
} 
: 마지막으로 우리는 믹스 인으로 페이징 세부 프록시를 만들 필요가

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

: 우리는 페이징 및 컬렉션 인터페이스를 결합하는 빈 인터페이스를 필요)를 ModelCollection와 PagingDetails 인터페이스의 프록시 캐스팅

그리고 지금 우리는 프록시를 사용할 수 있습니다 (이것은이 일을 내가 보장하기 위해 쓴 단위 테스트에서 가져온 것입니다) :

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)); 
관련 문제