/// <summary>
/// Creates a new ObjectReader instance for reading the supplied data
/// </summary>
/// <param name="type">The expected Type of the information to be read</param>
/// <param name="source">The sequence of objects to represent</param>
/// <param name="members">The members that should be exposed to the reader</param>
public ObjectReader(Type type, IEnumerable source, params string[] members)
{
if (source == null)
{
throw new ArgumentOutOfRangeException("source");
}
bool allMembers = members == null || members.Length == 0;
this.accessor = TypeAccessor.Create(type);
if (accessor.GetMembersSupported)
{
var typeMembers = this.accessor.GetMembers();
if (allMembers)
{
members = new string[typeMembers.Count];
for (int i = 0; i < members.Length; i++)
{
members[i] = typeMembers[i].Name;
}
}
this.allowNull = new BitArray(members.Length);
this.effectiveTypes = new Type[members.Length];
for (int i = 0; i < members.Length; i++)
{
Type memberType = null;
bool allowNull = true;
string hunt = members[i];
foreach (var member in typeMembers)
{
if (member.Name == hunt)
{
if (memberType == null)
{
var tmp = member.Type;
memberType = Nullable.GetUnderlyingType(tmp) ?? tmp;
allowNull = !(memberType.IsValueType && memberType == tmp);
// but keep checking, in case of duplicates
}
else
{
memberType = null; // duplicate found; say nothing
break;
}
}
}
this.allowNull[i] = allowNull;
this.effectiveTypes[i] = memberType ?? typeof(object);
}
}
else if (allMembers)
{
throw new InvalidOperationException("Member information is not available for this type; the required members must be specified explicitly");
}
this.current = null;
this.memberNames = (string[])members.Clone();
this.source = source.GetEnumerator();
}