private static Type GetEnumeratorElementType(Type type, ref TypeFlags flags)
{
if (typeof(IEnumerable).IsAssignableFrom(type))
{
MethodInfo enumerator = type.GetMethod("GetEnumerator", new Type[0]);
if (enumerator == null || !typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType))
{
// try generic implementation
enumerator = null;
foreach (MemberInfo member in type.GetMember("System.Collections.Generic.IEnumerable<*", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic))
{
enumerator = member as MethodInfo;
if (enumerator != null && typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType))
{
// use the first one we find
flags |= TypeFlags.GenericInterface;
break;
}
else
{
enumerator = null;
}
}
if (enumerator == null)
{
// and finally private interface implementation
flags |= TypeFlags.UsePrivateImplementation;
enumerator = type.GetMethod("System.Collections.IEnumerable.GetEnumerator", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic, Array.Empty<Type>());
}
}
if (enumerator == null || !typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType))
{
return null;
}
XmlAttributes methodAttrs = new XmlAttributes(enumerator);
if (methodAttrs.XmlIgnore) return null;
PropertyInfo p = enumerator.ReturnType.GetProperty("Current");
Type currentType = (p == null ? typeof(object) : p.PropertyType);
MethodInfo addMethod = type.GetMethod("Add", new Type[] { currentType });
if (addMethod == null && currentType != typeof(object))
{
currentType = typeof(object);
addMethod = type.GetMethod("Add", new Type[] { currentType });
}
if (addMethod == null)
{
throw new InvalidOperationException(SR.Format(SR.XmlNoAddMethod, type.FullName, currentType, "IEnumerable"));
}
return currentType;
}
else
{
return null;
}
}