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