#region Apache Notice /***************************************************************************** * $Revision: 374175 $ * $LastChangedDate$ * $LastChangedBy$ * * iBATIS.NET Data Mapper * Copyright (C) 2006/2005 - The Apache Software Foundation * * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ********************************************************************************/ #endregion using System; using System.Collections.Generic; using System.Collections; using System.Reflection; using IBatisNet.Common.Utilities.Objects.Members; using IBatisNet.DataMapper.MappedStatements; using IBatisNet.Common.Logging; namespace IBatisNet.DataMapper.Proxy { /// /// A lazy generic list /// /// [Serializable] public class LazyListGeneric : IList, IList where T: class { #region Fields private object _param = null; private object _target = null; private ISetAccessor _setAccessor = null; private ISqlMapper _sqlMap = null; private string _statementId = string.Empty; private bool _loaded = false; private object _loadLock = new object(); private IList _list = null; private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); #endregion /// /// Initializes a new instance of the LazyListGeneric class. /// /// The mapped satement. /// The param. /// The target. /// The set accessor. public LazyListGeneric(IMappedStatement mappedSatement, object param, object target, ISetAccessor setAccessor) { _param = param; _statementId = mappedSatement.Id; _sqlMap = mappedSatement.SqlMap; _target = target; _setAccessor = setAccessor; _list = new List(); } /// /// Resolve the lazy loading. /// /// Name of the method. private void Load(string methodName) { if (_logger.IsDebugEnabled) { _logger.Debug("Proxyfying call to " + methodName); } lock (_loadLock) { if (_loaded == false) { if (_logger.IsDebugEnabled) { _logger.Debug("Proxyfying call, query statement " + _statementId); } _list = _sqlMap.QueryForList(_statementId, _param); _loaded = true; _setAccessor.Set(_target, _list); } } if (_logger.IsDebugEnabled) { _logger.Debug("End of proxyfied call to " + methodName); } } #region IList Members /// /// Determines the index of a specific item in the . /// /// The object to locate in the . /// /// The index of item if found in the list; otherwise, -1. /// public int IndexOf(T item) { Load("IndexOf"); return _list.IndexOf(item); } /// /// Inserts an item to the at the specified index. /// /// The zero-based index at which item should be inserted. /// The object to insert into the . /// The is read-only. /// index is not a valid index in the . public void Insert(int index, T item) { Load("Insert"); _list.Insert(index, item); } /// /// Removes the item at the specified index. /// /// The zero-based index of the item to remove. /// The is read-only. /// index is not a valid index in the . public void RemoveAt(int index) { Load("RemoveAt"); _list.RemoveAt(index); } /// /// Gets or sets the object at the specified index. /// /// public T this[int index] { get { Load("this"); return _list[index]; } set { Load("this"); _list[index] = value; } } #endregion #region ICollection Members /// /// Adds an item to the . /// /// The object to add to the . /// The is read-only. public void Add(T item) { Load("Add"); _list.Add(item); } /// /// Removes all items from the . /// /// The is read-only. public void Clear() { Load("Clear"); _list.Clear(); } /// /// Determines whether the contains a specific value. /// /// The object to locate in the . /// /// true if item is found in the ; otherwise, false. /// public bool Contains(T item) { Load("Contains"); return _list.Contains(item); } /// /// Copies the elements of the to an , starting at a particular index. /// /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. /// The zero-based index in array at which copying begins. /// arrayIndex is less than 0. /// array is null. /// array is multidimensional.-or-arrayIndex is equal to or greater than the length of array.-or-The number of elements in the source is greater than the available space from arrayIndex to the end of the destination array.-or-Type T cannot be cast automatically to the type of the destination array. public void CopyTo(T[] array, int arrayIndex) { Load("CopyTo"); _list.CopyTo(array, arrayIndex); } /// /// Gets the number of elements contained in the . /// /// /// The number of elements contained in the . public int Count { get { Load("Count"); return _list.Count; } } /// /// Gets a value indicating whether the is read-only. /// /// /// true if the is read-only; otherwise, false. public bool IsReadOnly { get { return false; } } /// /// Removes the first occurrence of a specific object from the . /// /// The object to remove from the . /// /// true if item was successfully removed from the ; otherwise, false. This method also returns false if item is not found in the original . /// /// The is read-only. public bool Remove(T item) { Load("Remove"); return _list.Remove(item); } #endregion #region IEnumerable Members /// /// Returns an enumerator that iterates through the collection. /// /// /// A that can be used to iterate through the collection. /// public IEnumerator GetEnumerator() { Load("GetEnumerator"); return _list.GetEnumerator(); } #endregion #region IEnumerable Members /// /// Returns an enumerator that iterates through a collection. /// /// /// An object that can be used to iterate through the collection. /// IEnumerator IEnumerable.GetEnumerator() { Load("GetEnumerator"); return (System.Collections.IEnumerator)_list.GetEnumerator(); } #endregion #region IList Members /// /// Adds an item to the . /// /// The to add to the . /// /// The position into which the new element was inserted. /// /// The is read-only.-or- The has a fixed size. int IList.Add(object value) { Load("Add"); return ((IList)_list).Add(value); } /// /// Removes all items from the . /// /// The is read-only. void IList.Clear() { this.Clear(); } /// /// Determines whether the contains a specific value. /// /// The to locate in the . /// /// true if the is found in the ; otherwise, false. /// bool IList.Contains(object value) { Load("Contains"); return ((IList)_list).Contains(value); } /// /// Determines the index of a specific item in the . /// /// The to locate in the . /// /// The index of value if found in the list; otherwise, -1. /// int IList.IndexOf(object value) { Load("IndexOf"); return ((IList)_list).IndexOf(value); } /// /// Inserts an item to the at the specified index. /// /// The zero-based index at which value should be inserted. /// The to insert into the . /// index is not a valid index in the . /// The is read-only.-or- The has a fixed size. /// value is null reference in the . void IList.Insert(int index, object value) { Load("IndexOf"); ((IList)_list).Insert(index, value); } /// /// Gets a value indicating whether the has a fixed size. /// /// /// true if the has a fixed size; otherwise, false. bool IList.IsFixedSize { get { return false; } } /// /// Gets a value indicating whether the is read-only. /// /// /// true if the is read-only; otherwise, false. bool IList.IsReadOnly { get { return false; } } /// /// Removes the first occurrence of a specific object from the . /// /// The to remove from the . /// The is read-only.-or- The has a fixed size. void IList.Remove(object value) { Load("Remove"); ((IList)_list).Remove(value); } /// /// Removes the item at the specified index. /// /// The zero-based index of the item to remove. /// The is read-only. /// index is not a valid index in the . void IList.RemoveAt(int index) { this.RemoveAt(index); } /// /// Gets or sets the at the specified index. /// /// object IList.this[int index] { get { Load("this"); return this[index]; } set { Load("this"); ((IList)_list)[index] = value; } } #endregion #region ICollection Members /// /// Copies the elements of the to an , starting at a particular index. /// /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. /// The zero-based index in array at which copying begins. /// array is null. /// index is less than zero. /// array is multidimensional.-or- index is equal to or greater than the length of array.-or- The number of elements in the source is greater than the available space from index to the end of the destination array. /// The type of the source cannot be cast automatically to the type of the destination array. void ICollection.CopyTo(Array array, int index) { Load("CopyTo"); ((IList)_list).CopyTo(array, index); } /// /// Gets the number of elements contained in the . /// /// /// The number of elements contained in the . int ICollection.Count { get { return this.Count; } } /// /// Gets a value indicating whether access to the is synchronized (thread safe). /// /// /// true if access to the is synchronized (thread safe); otherwise, false. bool ICollection.IsSynchronized { get { return false; } } /// /// Gets an object that can be used to synchronize access to the . /// /// /// An object that can be used to synchronize access to the . object ICollection.SyncRoot { get { return this; } } #endregion } }