using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Collections.Concurrent; using System.Reflection.Emit; namespace Cosmos.Debug.Common { public class ObjectReader: IDataReader { private static readonly ConcurrentDictionary[]>> mInfo = new ConcurrentDictionary[]>>(); private readonly T[] mItems; private int mCurrentIndex = -1; // -1 is before first read, -2 is closed public ObjectReader(T[] items) { if (items == null) { throw new ArgumentNullException("items"); } mItems = items; Tuple[]> xInfo; if (mInfo.TryGetValue(typeof(T).FullName, out xInfo)) { mFieldGetters = xInfo.Item2; mFieldNames = xInfo.Item1; } else { Console.WriteLine("Detecting fields for type '{0}'", typeof(T).FullName); var props = typeof(T).GetProperties(); var xGetters = new List>(); var xNames = new List(); foreach (var prop in props) { var property = prop; xNames.Add(prop.Name); var dynMetho = new DynamicMethod("_" + Guid.NewGuid().ToString("n"), typeof(object), new Type[] { typeof(object) }); var gen = dynMetho.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Castclass, typeof(T)); gen.Emit(OpCodes.Call, prop.GetGetMethod()); if (prop.PropertyType.IsPrimitive || prop.PropertyType.IsValueType) { gen.Emit(OpCodes.Box, prop.PropertyType); } gen.Emit(OpCodes.Ret); xGetters.Add((Func)dynMetho.CreateDelegate(typeof(Func))); } mFieldNames = xNames.ToArray(); mFieldGetters = xGetters.ToArray(); mInfo.TryAdd(typeof(T).FullName, Tuple.Create[]>(mFieldNames, mFieldGetters)); } } private readonly string[] mFieldNames; private readonly Func[] mFieldGetters; public void Close() { mCurrentIndex = -2; } public int Depth { get { throw new NotImplementedException(); } } public DataTable GetSchemaTable() { throw new NotImplementedException(); } public bool IsClosed { get { return mCurrentIndex == -2; } } public bool NextResult() { throw new NotImplementedException(); } public bool Read() { mCurrentIndex++; return mCurrentIndex < mItems.Length; } public int RecordsAffected { get { return mItems.Length; } } public void Dispose() { Close(); } public int FieldCount { get { return mFieldNames.Length; } } public bool GetBoolean(int i) { throw new NotImplementedException(); } public byte GetByte(int i) { throw new NotImplementedException(); } public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); } public char GetChar(int i) { throw new NotImplementedException(); } 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) { throw new NotImplementedException(); } public decimal GetDecimal(int i) { throw new NotImplementedException(); } public double GetDouble(int i) { throw new NotImplementedException(); } public Type GetFieldType(int i) { throw new NotImplementedException(); } public float GetFloat(int i) { throw new NotImplementedException(); } public Guid GetGuid(int i) { throw new NotImplementedException(); } public short GetInt16(int i) { throw new NotImplementedException(); } public int GetInt32(int i) { throw new NotImplementedException(); } public long GetInt64(int i) { throw new NotImplementedException(); } public string GetName(int i) { return mFieldNames[i]; } public int GetOrdinal(string name) { throw new NotImplementedException(); } public string GetString(int i) { throw new NotImplementedException(); } public object GetValue(int i) { return mFieldGetters[i](mItems[mCurrentIndex]); } public int GetValues(object[] values) { throw new NotImplementedException(); } public bool IsDBNull(int i) { throw new NotImplementedException(); } public object this[string name] { get { throw new NotImplementedException(); } } public object this[int i] { get { throw new NotImplementedException(); } } } }