using System; using System.Collections.Generic; using System.Data; using System.Reflection; using Fasterflect; namespace DataModel.Helpers { /// /// IEnumerable extension helpers /// public static class GenericListDataReaderExtensions { /// /// Generates generic data reader for bulk copies from list /// /// Element data type /// Source list /// Data reader to parse list contents public static GenericListDataReader GetDataReader(this IEnumerable list) where T : class { return new GenericListDataReader(list); } } /// /// Data reader that parses list of generic elements /// public class GenericListDataReader : IDataReader { public int Count { get; set; } private readonly IEnumerator list = null; private readonly List properties = new List(); private readonly Dictionary nameLookup = new Dictionary(); private readonly string[] propertyNames; public GenericListDataReader(IEnumerable list, Type type) { this.list = list.GetEnumerator(); properties.AddRange(type.GetProperties(BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)); propertyNames = new string[properties.Count]; for (int i = 0; i < properties.Count; i++) { nameLookup[properties[i].Name] = i; propertyNames[i] = properties[i].Name; } } public void Close() { list.Dispose(); } public int Depth => throw new NotImplementedException(); public DataTable GetSchemaTable() { throw new NotImplementedException(); } public bool IsClosed => false; public bool NextResult() { throw new NotImplementedException(); } public bool Read() { bool readResult = list.MoveNext(); //Update counter if (readResult) { Count++; } return readResult; } public int RecordsAffected => throw new NotImplementedException(); public void Dispose() { Close(); } public int FieldCount => properties.Count; public bool GetBoolean(int i) { return (bool)GetValue(i); } public byte GetByte(int i) { return (byte)GetValue(i); } public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); } public char GetChar(int i) { return (char)GetValue(i); } public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); } public IDataReader GetData(int i) { throw new NotImplementedException(); } public string GetDataTypeName(int i) { throw new NotImplementedException(); } public DateTime GetDateTime(int i) { return (DateTime)GetValue(i); } public decimal GetDecimal(int i) { return (decimal)GetValue(i); } public double GetDouble(int i) { return (double)GetValue(i); } public Type GetFieldType(int i) { return properties[i].PropertyType; } public float GetFloat(int i) { return (float)GetValue(i); } public Guid GetGuid(int i) { return (Guid)GetValue(i); } public short GetInt16(int i) { return (short)GetValue(i); } public int GetInt32(int i) { return (int)GetValue(i); } public long GetInt64(int i) { return (long)GetValue(i); } public string GetName(int i) { return properties[i].Name; } public int GetOrdinal(string name) { if (nameLookup.ContainsKey(name)) { return nameLookup[name]; } else { return -1; } } public string GetString(int i) { return (string)GetValue(i); } public object GetValue(int i) { string name = propertyNames[i]; return list.Current.GetPropertyValue(name); } public int GetValues(object[] values) { int getValues = Math.Max(FieldCount, values.Length); for (int i = 0; i < getValues; i++) { values[i] = GetValue(i); } return getValues; } public bool IsDBNull(int i) { return GetValue(i) == null; } public object this[string name] => list.Current.GetPropertyValue(name); public object this[int i] => GetValue(i); } /// /// Data reader that parses list of generic elements /// /// Element data type public class GenericListDataReader : GenericListDataReader where T : class { public GenericListDataReader(IEnumerable list) : base(list, typeof(T)) { } } }