// Copyright 2009-2022 Josh Close // This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. // See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. // https://github.com/JoshClose/CsvHelper using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace CsvHelper.Configuration { /// /// A collection that holds 's. /// [DebuggerDisplay("Count = {list.Count}")] public class MemberMapCollection : IList { private readonly List list = new List(); private readonly IComparer comparer; /// /// Gets the number of elements contained in the . /// /// /// The number of elements contained in the . /// public virtual int Count => list.Count; /// /// Gets a value indicating whether the is read-only. /// /// /// true if the is read-only; otherwise, false. /// public virtual bool IsReadOnly => false; /// /// Initializes a new instance of the class. /// public MemberMapCollection() : this(new MemberMapComparer()) { } /// /// Initializes a new instance of the class. /// /// The comparer to use when sorting the member maps. public MemberMapCollection(IComparer comparer) { this.comparer = comparer; } /// /// Returns an enumerator that iterates through the collection. /// /// /// A that can be used to iterate through the collection. /// /// 1 public virtual IEnumerator GetEnumerator() { return list.GetEnumerator(); } /// /// Returns an enumerator that iterates through a collection. /// /// /// An object that can be used to iterate through the collection. /// /// 2 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// Adds an item to the . /// /// The object to add to the . /// The is read-only. /// public virtual void Add(MemberMap item) { list.Add(item); list.Sort(comparer); } /// /// Adds a range of items to the . /// /// The collection to add. public virtual void AddRange(ICollection collection) { list.AddRange(collection); list.Sort(comparer); } /// /// Removes all items from the . /// /// The is read-only. /// public virtual void Clear() { list.Clear(); } /// /// Determines whether the contains a specific value. /// /// /// true if is found in the ; otherwise, false. /// /// The object to locate in the . /// public virtual bool Contains(MemberMap item) { 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 at which copying begins. is null. is less than 0.The number of elements in the source is greater than the available space from to the end of the destination . public virtual void CopyTo(MemberMap[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } /// /// Removes the first occurrence of a specific object from the . /// /// /// true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . /// /// The object to remove from the . /// The is read-only. /// public virtual bool Remove(MemberMap item) { return list.Remove(item); } /// /// Determines the index of a specific item in the . /// /// /// The index of if found in the list; otherwise, -1. /// /// The object to locate in the . /// public virtual int IndexOf(MemberMap item) { return list.IndexOf(item); } /// /// Inserts an item to the at the specified index. /// /// The zero-based index at which should be inserted. /// The object to insert into the . /// is not a valid index in the . /// The is read-only. /// public virtual void Insert(int index, MemberMap item) { list.Insert(index, item); } /// /// Removes the item at the specified index. /// /// The zero-based index of the item to remove. /// is not a valid index in the . /// The is read-only. /// public virtual void RemoveAt(int index) { list.RemoveAt(index); } /// /// Gets or sets the element at the specified index. /// /// /// The element at the specified index. /// /// The zero-based index of the element to get or set. /// is not a valid index in the . /// The member is set and the is read-only. /// public virtual MemberMap this[int index] { get { return list[index]; } set { list[index] = value; } } /// /// Finds the using the given member expression. /// /// The the member is on. /// The member expression. /// The for the given expression, or null if not found. public virtual MemberMap? Find(Expression> expression) { var member = ReflectionHelper.GetMember(expression); return Find(member); } /// /// Finds the using the given member. /// /// The member. /// The for the given expression, or null if not found. public virtual MemberMap? Find(MemberInfo member) { var existingMap = list.SingleOrDefault(m => m.Data.Member == member || m.Data.Member != null && m.Data.Member.Name == member.Name && ( m.Data.Member.DeclaringType.IsAssignableFrom(member.DeclaringType) || member.DeclaringType.IsAssignableFrom(m.Data.Member.DeclaringType) ) ); return existingMap; } /// /// Adds the members from the mapping. This will recursively /// traverse the mapping tree and add all members for /// reference maps. /// /// The mapping where the members are added from. public virtual void AddMembers(ClassMap mapping) { AddRange(mapping.MemberMaps); foreach (var refmap in mapping.ReferenceMaps) { AddMembers(refmap.Data.Mapping); } } } }