使 ICollection 像 IList 一样工作

Make ICollection work as IList

我正在尝试使用 MvvmLight 在 Xamarin 中进行 ViewModel 绑定 Android

MvvmLight 接受 IList 作为数据绑定的参数,但所有视图模型都使用 ICollection(该应用程序最初仅 windows,目前正在迁移到 Android,我们无法将 ICollection 更改为IList)

我知道 IList 扩展了 ICollection,所以..我想这更像是一种模式化的东西,我们让这些 ICollection 像 IList 一样工作的最佳方式是什么?

转换是显而易见的解决方案,但并非所有 ICollection 都实现 IList,因此我们正在努力避免这种情况

我们也无法复制原始集合,因为我们需要双向绑定

由于无法保证任意 ICollection<T> 也是 IList<T>,最简单的方法是使用 Adapter Pattern:需要 (IList<T>).

IList<T> 是一个非常简单的界面,您应该能够按照这些思路做一些事情(参见下面的示例),尽管有人可能会注意到 IList<T> 提供的某些功能根本不兼容具有任意 ICollection<T> 实现。根据消费者使用的具体 IList<T> 功能,您可以抛出 NotSupportedExceptions.

人们可能还会注意到,您可以在适配器中变得更聪明一些,并使用 反射 来询问后备存储的实际功能——我下面的示例做了一个简单的版本,尝试将后备存储转换为 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() ;
    }

}