Feeling lazy part two
In my earlier post I talked about the lazy observable collection I created so that I could lazy load an observable collection so that I wasn't loading the entire collection until it was absolutely necessary. As a companion to that piece of work I also created a lazy read only observable collection. This brings the same features as the lazy observable collection except with advantage, depending on your viewpoint, of being read only.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
namespace Lazy
{
/// <summary>
/// represents a LazyReadOnlyCollection class that uses IQueryable for delayed loading and implements ICollection, INotifyCollectionChanged and INotifyPropertyChanged
/// </summary>
/// <typeparam name="T">the object type T</typeparam>
public class LazyReadOnlyCollection<T> : ICollection<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
#region members
private readonly LazyCollection<T> _collection;
#endregion
#region properties
/// <summary>
/// gets whether the collection has been loaded
/// </summary>
public bool HasLoaded
{
get { return _collection.HasLoaded; }
}
/// <summary>
/// gets the item from the list at the specified index
/// </summary>
/// <param name="index">the index of the item in the list</param>
/// <returns>the item</returns>
public T this[int index]
{
get
{
return _collection[index];
}
}
#endregion
#region constructors
/// <summary>
/// default constructor
/// </summary>
/// <param name="collection">a LazyCollection of type T</param>
public LazyReadOnlyCollection(LazyCollection<T> collection)
{
//set properties
_collection = collection;
//subscribe to events
_collection.CollectionChanged += HandleCollectionChanged;
_collection.PropertyChanged += HandlePropertyChanged;
}
#endregion
#region methods
#endregion
#region ICollection<T> Members
/// <summary>
/// adds the item to the collection
/// </summary>
/// <param name="item">the item to add</param>
public void Add(T item)
{
throw new NotImplementedException("The collection is read only");
}
/// <summary>
/// clears the collection
/// </summary>
public void Clear()
{
throw new NotImplementedException("The collection is read only");
}
/// <summary>
/// determines whether the item is contained within the collection
/// </summary>
/// <param name="item">the item to find</param>
/// <returns>a boolean value indicating whether the item was found</returns>
public bool Contains(T item)
{
return _collection.Contains(item);
}
/// <summary>
/// copies the collection to an array starting at the specified index
/// </summary>
/// <param name="array">the target array</param>
/// <param name="arrayIndex">the starting index</param>
public void CopyTo(T[] array, int arrayIndex)
{
_collection.CopyTo(array, arrayIndex);
}
/// <summary>
/// gets the number of items in the collection
/// </summary>
public int Count
{
get { return _collection.Count; }
}
/// <summary>
/// determines whether the collection is read only
/// </summary>
public bool IsReadOnly
{
get { return true; }
}
/// <summary>
/// removes the item from the collection
/// </summary>
/// <param name="item">the item to remove</param>
/// <returns>a boolean value indicating whether the item was removed</returns>
public bool Remove(T item)
{
throw new NotImplementedException("The collection is read only");
}
#endregion
#region IEnumerable<T> Members
/// <summary>
/// gets the enumerator to iterate over the collection
/// </summary>
/// <returns>IEnumerator</returns>
public IEnumerator<T> GetEnumerator()
{
return _collection.GetEnumerator();
}
#endregion
#region IEnumerable Members
/// <summary>
/// gets the enumerator to iterate over the collection
/// </summary>
/// <returns>IEnumerator</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return _collection.GetEnumerator();
}
#endregion
#region INotifyCollectionChanged Members
/// <summary>
/// CollectionChanged event
/// </summary>
public event NotifyCollectionChangedEventHandler CollectionChanged;
/// <summary>
/// handles the collection changed events of the inner collection and forwards them on
/// </summary>
/// <param name="sender">the object that raised the event</param>
/// <param name="e">NotifyCollectionChangedEventArgs</param>
void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnCollectionChanged(e);
}
/// <summary>
/// raises the CollectionChanged event
/// </summary>
/// <param name="e">NotifyCollectionChangedEventArgs</param>
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged != null)
{
CollectionChanged(this, e);
}
}
#endregion
#region INotifyPropertyChanged Members
/// <summary>
/// PropertyChanged event
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// handles the property changed events from the inner collection and forwards them on
/// </summary>
/// <param name="sender">the object that raised the event</param>
/// <param name="e">PropertyChangedEventArgs</param>
void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e);
}
/// <summary>
/// raises the PropertyChanged event
/// </summary>
/// <param name="e">PropertyChangedEventArgs</param>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
#endregion
#region Monitor
/// <summary>
/// represents a Monitor class that implements IDisposable
/// </summary>
/// <remarks>used to prevent reentrant calls</remarks>
private class Monitor : IDisposable
{
#region members
private int _busyCount;
#endregion
#region properties
/// <summary>
/// gets the busy state
/// </summary>
public bool Busy
{
get { return _busyCount > 0; }
}
#endregion
#region constructors
/// <summary>
/// default constructor
/// </summary>
public Monitor()
{
}
#endregion
#region methods
/// <summary>
/// increments the busy count
/// </summary>
public void Enter()
{
++_busyCount;
}
#endregion
#region IDisposable Members
/// <summary>
/// decrements the busy count
/// </summary>
public void Dispose()
{
--_busyCount;
}
#endregion
}
#endregion
}
}

0 Comments