/// <summary> /// Populates the properties of an object from a single DataReader row using /// Reflection by matching the DataReader fields to a public property on /// the object passed in. Unmatched properties are left unchanged. /// /// You need to pass in a data reader located on the active row you want /// to serialize. /// /// This routine works best for matching pure data entities and should /// be used only in low volume environments where retrieval speed is not /// critical due to its use of Reflection. /// </summary> /// <param name="reader">Instance of the DataReader to read data from. Should be located on the correct record (Read() should have been called on it before calling this method)</param> /// <param name="instance">Instance of the object to populate properties on</param> /// <param name="fieldsToSkip">Optional - A comma delimited list of object properties that should not be updated</param> /// <param name="piList">Optional - Cached PropertyInfo dictionary that holds property info data for this object</param> public static void DataReaderToObject(this IDataReader reader, ref object instance, Type type = null, string fieldsToSkip = null, Dictionary <string, PropertyInfo> piList = null) { if (reader.IsClosed) { throw new InvalidOperationException("Data reader cannot be used because it's already closed"); } var _type = instance == null ? type : instance.GetType(); if (_type.IsNullableOrBasicType()) { var value = reader[0]; if (value != null && !DBNull.Value.Equals(value)) { if (_type == TypeHelper.TypeOfString) { instance = Activator.CreateInstance(TypeHelper.TypeOfString, SafeClrConvert.ToString(value).ToCharArray()); } else { instance = SafeClrConvert.ChangeType(value, _type); } } return; } if (string.IsNullOrEmpty(fieldsToSkip)) { fieldsToSkip = string.Empty; } else { fieldsToSkip = "," + fieldsToSkip + ","; } fieldsToSkip = fieldsToSkip.ToLower(); // create a dictionary of properties to look up // we can pass this in so we can cache the list once // for a list operation if (piList == null) { piList = new Dictionary <string, PropertyInfo>(); var props = _type.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (var prop in props) { piList.Add(prop.Name.ToLower(), prop); } } for (var index = 0; index < reader.FieldCount; index++) { var name = reader.GetName(index).ToLower(); if (piList.ContainsKey(name)) { var prop = piList[name]; if (fieldsToSkip.Contains("," + name + ",")) { continue; } if ((prop != null) && prop.CanWrite) { var val = reader.GetValue(index); prop.SetValue(instance, (val == DBNull.Value) ? null : val, null); } } } }