2015-02-11 6 views
0

Я пытаюсь использовать MvvmLight сделать ViewModel связывание в Xamarin AndroidMake ICollection работать как IList

MvvmLight принимает IList в качестве параметра для связывания данных, но все ViewModels используют ICollection (приложение первоначально было только окна и в настоящее время переносится на Android, мы не можем изменить ICollection на IList)

Я знаю, что IList расширяет ICollection, так что..Я думаю, что это скорее образец-то, что является лучшим способом, который мы делаем, чтобы эти ICollection работали как IList?

Casting является очевидным решением, но не все ICollection реализует IList, поэтому мы пытаемся избежать этого

Мы также не можем сделать копию оригинальной коллекции, потому что нам нужно двухстороннее связывание

+2

Вы можете создать оболочку, реализующую IList, которая маршрутизирует вызовы в базовую коллекцию. Это также может позаботиться о частичной эмуляции индексации (предполагая, что Xamarin использует это) с ElementAt. Это ломается, если реализация потребления пытается выполнить вставку, хотя, поскольку вы не можете выполнить вставку с произвольным доступом; вам нужно будет восстановить всю коллекцию в этом случае, удалив все, а затем добавив ее снова. –

ответ

4

Поскольку не является гарантией того, что произвольный ICollection<T> также является IList<T>, самым простым способом является использование Adapter Pattern: Напишите тонкую прокладку, которая обеспечивает необходимый вам интерфейс (IList<T>).

IList<T> является довольно простым интерфейсом, и вы должны быть в состоянии сделать что-то вдоль этих линий (смотрите пример ниже), хотя можно отметить, что IList<T> предоставляет определенные возможности, которые просто не совместимы с произвольными ICollection<T> реализациями. В зависимости от того, какой конкретный IList<T> использует потребитель (ы), вы можете выбросить NotSupportedException с.

Можно также отметить, что вы могли бы получить немного умнее в адаптер и использовать Reflection опрашивать резервное хранилище для своих реальных возможностей — мой пример ниже делает простой вариант, пытаясь бросить подкладочный магазин IList<T> и используя это знание там, где это возможно.

class ListAdapter<T> : IList<T> 
{ 
    private readonly ICollection<T> backingStore; 
    private readonly IList<T> list; 

    public ListAdapter(ICollection<T> collection) 
    { 
     if (collection == null) throw new ArgumentNullException("collection"); 
     this.backingStore = collection ; 
     this.list = collection as IList<T> ; 

    } 

    public int IndexOf(T item) 
    { 
     if (list == null) throw new NotSupportedException() ; 
     return list.IndexOf(item) ; 
    } 

    public void Insert(int index , T item) 
    { 
     if (list == null) throw new NotSupportedException() ; 
     list.Insert(index,item); 
    } 

    public void RemoveAt(int index) 
    { 
     if (list == null) throw new NotSupportedException() ; 
     list.RemoveAt(index) ; 
    } 

    public T this[int index] 
    { 
     get 
     { 
      if (list == null) throw new NotSupportedException() ; 
      return list[index] ; 
     } 
     set 
     { 
      if (list == null) throw new NotSupportedException() ; 
      list[index] = value ; 
     } 
    } 

    public void Add(T item) 
    { 
     backingStore.Add(item) ; 
    } 

    public void Clear() 
    { 
     backingStore.Clear() ; 
    } 

    public bool Contains(T item) 
    { 
     return backingStore.Contains(item) ; 
    } 

    public void CopyTo(T[] array , int arrayIndex) 
    { 
     backingStore.CopyTo(array , arrayIndex) ; 
    } 

    public int Count 
    { 
     get { return backingStore.Count ; } 
    } 

    public bool IsReadOnly 
    { 
     get 
     { 
      if (list == null) throw new NotSupportedException() ; 
      return list.IsReadOnly ; 
     } 
    } 

    public bool Remove(T item) 
    { 
     return backingStore.Remove(item) ; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     return backingStore.GetEnumerator() ; 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return ((System.Collections.IEnumerable)backingStore).GetEnumerator() ; 
    } 

}