public static Type GetXsdType <T>(this XSerializerXmlReader reader, Type[] extraTypes)
{
string typeName = null;
while (reader.MoveToNextAttribute())
{
if (reader.LocalName == "type" && reader.LookupNamespace(reader.Prefix) == "http://www.w3.org/2001/XMLSchema-instance")
{
typeName = reader.Value;
break;
}
}
reader.MoveToElement();
if (typeName == null)
{
return(null);
}
Type typeFromXsdType;
if (_xsdTypeToTypeMap.TryGetValue(typeName, out typeFromXsdType))
{
return(typeFromXsdType);
}
return(_xsdTypeToTypeCache.GetOrAdd(
Tuple.Create(typeof(T), typeName),
_ =>
{
Type type = null;
//// try REAL hard to get the type. (holy crap, this is UUUUUGLY!!!!)
if (extraTypes != null)
{
var matchingExtraTypes = extraTypes.Where(t => t.Name == typeName && typeof(T).IsAssignableFrom(t)).ToList();
if (matchingExtraTypes.Count == 1)
{
type = matchingExtraTypes[0];
}
}
if (type == null)
{
var typeNameWithPossibleNamespace = typeName;
if (!typeName.Contains('.'))
{
typeNameWithPossibleNamespace = typeof(T).Namespace + "." + typeName;
}
var checkPossibleNamespace = typeName != typeNameWithPossibleNamespace;
type = Type.GetType(typeName);
type = typeof(T).IsAssignableFrom(type) ? type : null;
if (type == null)
{
type = checkPossibleNamespace ? Type.GetType(typeNameWithPossibleNamespace) : null;
type = typeof(T).IsAssignableFrom(type) ? type : null;
if (type == null)
{
type = typeof(T).Assembly.GetType(typeName);
type = typeof(T).IsAssignableFrom(type) ? type : null;
if (type == null)
{
type = checkPossibleNamespace ? typeof(T).Assembly.GetType(typeNameWithPossibleNamespace) : null;
type = typeof(T).IsAssignableFrom(type) ? type : null;
if (type == null)
{
var matches = typeof(T).Assembly.GetTypes().Where(t => t.Name == typeName && typeof(T).IsAssignableFrom(t)).ToList();
if (matches.Count == 1)
{
type = matches.Single();
}
var entryAssembly = Assembly.GetEntryAssembly();
if (entryAssembly != null)
{
type = entryAssembly.GetType(typeName);
type = typeof(T).IsAssignableFrom(type) ? type : null;
if (type == null)
{
type = checkPossibleNamespace ? entryAssembly.GetType(typeNameWithPossibleNamespace) : null;
type = typeof(T).IsAssignableFrom(type) ? type : null;
}
if (type == null)
{
matches = entryAssembly.GetTypes().Where(t => t.Name == typeName && typeof(T).IsAssignableFrom(t)).ToList();
if (matches.Count == 1)
{
type = matches.Single();
}
}
}
if (type == null)
{
matches = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a =>
{
try
{
return a.GetTypes();
}
catch
{
return Enumerable.Empty <Type>();
}
}).Where(t => t.Name == typeName && typeof(T).IsAssignableFrom(t)).ToList();
if (matches.Count == 1)
{
type = matches.Single();
}
else if (matches.Count > 1)
{
throw new SerializationException(string.Format("More than one type matches '{0}'. Consider decorating your type with the XmlIncludeAttribute, or pass in the type into the serializer as an extra type.", typeName));
}
}
}
}
}
}
}
if (type == null)
{
throw new SerializationException(string.Format("No suitable type matches '{0}'. Consider decorating your type with the XmlIncludeAttribute, or pass in the type into the serializer as an extra type.", typeName));
}
return type;
}));
}