Were either
InnerList or
List properties of CollectionBase virtual, it would be pretty straightforward. Unfortunatelly, this is not the case. Nevertheless it is still doable. Essentially, you have to write a typed IList-wrapper, which delegates all calls to a wrapped list. Here's how I do that (please note explicit interface implementations):
Code:
namespace CommonServer.ObjectModel.Business.Collections
{
public abstract class ListWrapperBase : IList
{
#region Private Member Variables
private IList wrappedList;
#endregion
#region Protected Properties
protected IList WrappedList
{
get { return wrappedList; }
}
#endregion
public ListWrapperBase(IList wrappedList)
{
this.wrappedList = wrappedList;
}
#region IList Members
public bool IsReadOnly
{
get { return wrappedList.IsReadOnly; }
}
public bool IsFixedSize
{
get { return wrappedList.IsFixedSize; }
}
int IList.Add(object value)
{
return wrappedList.Add(value);
}
bool IList.Contains(object value)
{
return wrappedList.Contains(value);
}
public void Clear()
{
wrappedList.Clear();
}
int IList.IndexOf(object value)
{
return wrappedList.IndexOf(value);
}
void IList.Insert(int index, object value)
{
wrappedList.Insert(index, value);
}
void IList.Remove(object value)
{
wrappedList.Remove(value);
}
public void RemoveAt(int index)
{
wrappedList.RemoveAt(index);
}
object IList.this[int index]
{
get { return wrappedList[index]; }
set { wrappedList[index] = value; }
}
public int Count
{
get { return wrappedList.Count; }
}
public object SyncRoot
{
get { return wrappedList.SyncRoot; }
}
public bool IsSynchronized
{
get { return wrappedList.IsSynchronized; }
}
public void CopyTo(Array array, int index)
{
wrappedList.CopyTo(array, index);
}
public IEnumerator GetEnumerator()
{
return wrappedList.GetEnumerator();
}
#endregion
}
}
And here's a typed ancestor:
Code:
using System.Collections;
using CommonServer.ObjectModel.Business.Objects;
namespace CommonServer.ObjectModel.Business.Collections
{
public class CityListWrapper : ListWrapperBase
{
public City this[int index]
{
get { return WrappedList[index] as City; }
set { WrappedList[index] = value; }
}
public CityListWrapper(IList wrappedList) :
base(wrappedList)
{
}
public int Add(City businessObject)
{
return WrappedList.Add(businessObject);
}
public bool Contains(City businessObject)
{
return WrappedList.Contains(businessObject);
}
public int IndexOf(City businessObject)
{
return WrappedList.IndexOf(businessObject);
}
public void Insert(int index, City businessObject)
{
WrappedList.Insert(index, businessObject);
}
public void Remove(City businessObject)
{
WrappedList.Remove(businessObject);
}
}
}
And finally business object, which contains a collection of City objects (Country in my case)
Code:
public class Country
{
private IList cities = new ArrayList();
// Yes, creating a new instance of CityListWrapper is performance penalty
public CityListWrapper Cities
{ get { return new CityListWrapper(cities); } }
}