Added support for case-insensitive type lookup.

This commit is contained in:
jfrijters 2012-04-09 10:04:58 +00:00
Родитель bc16ad7c47
Коммит b2a6a24bde
14 изменённых файлов: 182 добавлений и 28 удалений

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2009 Jeroen Frijters
Copyright (C) 2009-2012 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -51,6 +51,7 @@ namespace IKVM.Reflection
public abstract System.IO.Stream GetManifestResourceStream(string name);
internal abstract Type FindType(TypeName name);
internal abstract Type FindTypeIgnoreCase(TypeName lowerCaseName);
// The differences between ResolveType and FindType are:
// - ResolveType is only used when a type is assumed to exist (because another module's metadata claims it)
@ -110,10 +111,6 @@ namespace IKVM.Reflection
public Type GetType(string name, bool throwOnError, bool ignoreCase)
{
if (ignoreCase)
{
throw new NotImplementedException();
}
TypeNameParser parser = TypeNameParser.Parse(name, throwOnError);
if (parser.Error)
{
@ -131,12 +128,14 @@ namespace IKVM.Reflection
}
}
TypeName typeName = TypeName.Split(TypeNameParser.Unescape(parser.FirstNamePart));
Type type = FindType(typeName);
Type type = ignoreCase
? FindTypeIgnoreCase(typeName.ToLowerInvariant())
: FindType(typeName);
if (type == null && __IsMissing)
{
throw new MissingAssemblyException((MissingAssembly)this);
}
return parser.Expand(type, this, throwOnError, name, false);
return parser.Expand(type, this, throwOnError, name, false, ignoreCase);
}
public virtual Module LoadModule(string moduleName, byte[] rawModule)

Просмотреть файл

@ -428,7 +428,7 @@ namespace IKVM.Reflection
// there are broken compilers that emit an extra NUL character after the type name
typeName = typeName.Substring(0, typeName.Length - 1);
}
return TypeNameParser.Parse(typeName, true).GetType(asm.universe, asm, true, typeName, true);
return TypeNameParser.Parse(typeName, true).GetType(asm.universe, asm, true, typeName, true, false);
}
private static IList<CustomAttributeTypedArgument> ReadConstructorArguments(Assembly asm, ByteReader br, ConstructorInfo constructor)

Просмотреть файл

@ -577,6 +577,27 @@ namespace IKVM.Reflection.Emit
return null;
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
foreach (ModuleBuilder mb in modules)
{
Type type = mb.FindTypeIgnoreCase(lowerCaseName);
if (type != null)
{
return type;
}
}
foreach (Module module in addedModules)
{
Type type = module.FindTypeIgnoreCase(lowerCaseName);
if (type != null)
{
return type;
}
}
return null;
}
public override string ImageRuntimeVersion
{
get { return imageRuntimeVersion; }
@ -716,6 +737,11 @@ namespace IKVM.Reflection.Emit
return null;
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
return null;
}
internal override void GetTypesImpl(List<Type> list)
{
}

Просмотреть файл

@ -471,6 +471,18 @@ namespace IKVM.Reflection.Emit
return null;
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
foreach (Type type in types)
{
if (new TypeName(type.__Namespace, type.__Name).ToLowerInvariant() == lowerCaseName)
{
return type;
}
}
return null;
}
internal override void GetTypesImpl(List<Type> list)
{
foreach (Type type in types)

Просмотреть файл

@ -113,7 +113,7 @@ namespace IKVM.Reflection
TypeNameParser parser = TypeNameParser.Parse(marshalType, false);
if (!parser.Error)
{
marshalTypeRef = parser.GetType(module.universe, module.Assembly, false, marshalType, false);
marshalTypeRef = parser.GetType(module.universe, module.Assembly, false, marshalType, false, false);
}
}

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2011 Jeroen Frijters
Copyright (C) 2011-2012 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -223,6 +223,11 @@ namespace IKVM.Reflection
return null;
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
return null;
}
internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
{
throw new MissingAssemblyException(this);
@ -274,6 +279,11 @@ namespace IKVM.Reflection
return null;
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
return null;
}
internal override void GetTypesImpl(System.Collections.Generic.List<Type> list)
{
throw new MissingModuleException(this);
@ -378,6 +388,11 @@ namespace IKVM.Reflection
return null;
}
internal override Type FindNestedTypeIgnoreCase(TypeName lowerCaseName)
{
return null;
}
public override bool __IsMissing
{
get { return true; }

Просмотреть файл

@ -309,6 +309,7 @@ namespace IKVM.Reflection
internal abstract void GetTypesImpl(List<Type> list);
internal abstract Type FindType(TypeName name);
internal abstract Type FindTypeIgnoreCase(TypeName lowerCaseName);
[Obsolete("Please use __ResolveOptionalParameterTypes(int, Type[], Type[], out CustomModifiers[]) instead.")]
public Type[] __ResolveOptionalParameterTypes(int metadataToken)
@ -329,10 +330,6 @@ namespace IKVM.Reflection
public Type GetType(string className, bool throwOnError, bool ignoreCase)
{
if (ignoreCase)
{
throw new NotImplementedException();
}
TypeNameParser parser = TypeNameParser.Parse(className, throwOnError);
if (parser.Error)
{
@ -349,12 +346,15 @@ namespace IKVM.Reflection
return null;
}
}
Type type = FindType(TypeName.Split(TypeNameParser.Unescape(parser.FirstNamePart)));
TypeName typeName = TypeName.Split(TypeNameParser.Unescape(parser.FirstNamePart));
Type type = ignoreCase
? FindTypeIgnoreCase(typeName.ToLowerInvariant())
: FindType(typeName);
if (type == null && __IsMissing)
{
throw new MissingModuleException((MissingModule)this);
}
return parser.Expand(type, this.Assembly, throwOnError, className, false);
return parser.Expand(type, this.Assembly, throwOnError, className, false, ignoreCase);
}
public Type[] GetTypes()

Просмотреть файл

@ -109,6 +109,19 @@ namespace IKVM.Reflection.Reader
return type;
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
Type type = manifestModule.FindTypeIgnoreCase(lowerCaseName);
for (int i = 0; type == null && i < externalModules.Length; i++)
{
if ((manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0)
{
type = GetModule(i).FindTypeIgnoreCase(lowerCaseName);
}
}
return type;
}
public override string ImageRuntimeVersion
{
get { return manifestModule.__ImageRuntimeVersion; }

Просмотреть файл

@ -141,6 +141,11 @@ namespace IKVM.Reflection.Reader
throw new InvalidOperationException();
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
throw new InvalidOperationException();
}
internal override void GetTypesImpl(List<Type> list)
{
throw new InvalidOperationException();

Просмотреть файл

@ -589,6 +589,26 @@ namespace IKVM.Reflection.Reader
return type;
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
PopulateTypeDef();
foreach (Type type in types.Values)
{
if (new TypeName(type.__Namespace, type.__Name).ToLowerInvariant() == lowerCaseName)
{
return type;
}
}
foreach (TypeName name in forwardedTypes.Keys)
{
if (name.ToLowerInvariant() == lowerCaseName)
{
return forwardedTypes[name].GetType(this, name);
}
}
return null;
}
private Exception TokenOutOfRangeException(int metadataToken)
{
return new ArgumentOutOfRangeException("metadataToken", String.Format("Token 0x{0:x8} is not valid in the scope of module {1}.", metadataToken, this.Name));

Просмотреть файл

@ -90,6 +90,11 @@ namespace IKVM.Reflection.Reader
return null;
}
internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
return null;
}
internal override void GetTypesImpl(List<Type> list)
{
}

Просмотреть файл

@ -865,6 +865,18 @@ namespace IKVM.Reflection
return null;
}
internal virtual Type FindNestedTypeIgnoreCase(TypeName lowerCaseName)
{
foreach (Type type in __GetDeclaredTypes())
{
if (new TypeName(type.__Namespace, type.__Name).ToLowerInvariant() == lowerCaseName)
{
return type;
}
}
return null;
}
public Type GetNestedType(string name)
{
return GetNestedType(name, BindingFlags.Public);

Просмотреть файл

@ -1,5 +1,5 @@
/*
Copyright (C) 2009-2011 Jeroen Frijters
Copyright (C) 2009-2012 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -23,6 +23,7 @@
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace IKVM.Reflection
@ -86,6 +87,11 @@ namespace IKVM.Reflection
return this == other;
}
internal TypeName ToLowerInvariant()
{
return new TypeName(ns == null ? null : ns.ToLowerInvariant(), name.ToLowerInvariant());
}
internal static TypeName Split(string name)
{
int dot = name.LastIndexOf('.');
@ -449,8 +455,9 @@ namespace IKVM.Reflection
}
}
internal Type GetType(Universe universe, Assembly context, bool throwOnError, string originalName, bool resolve)
internal Type GetType(Universe universe, Assembly context, bool throwOnError, string originalName, bool resolve, bool ignoreCase)
{
Debug.Assert(!resolve || !ignoreCase);
TypeName name = TypeName.Split(this.name);
Type type;
if (assemblyName != null)
@ -464,6 +471,10 @@ namespace IKVM.Reflection
{
type = asm.ResolveType(name);
}
else if (ignoreCase)
{
type = asm.FindTypeIgnoreCase(name.ToLowerInvariant());
}
else
{
type = asm.FindType(name);
@ -475,18 +486,37 @@ namespace IKVM.Reflection
{
type = universe.Mscorlib.ResolveType(name);
}
else if (ignoreCase)
{
type = universe.Mscorlib.FindTypeIgnoreCase(name.ToLowerInvariant());
}
else
{
type = universe.Mscorlib.FindType(name);
}
}
else
{
if (ignoreCase)
{
name = name.ToLowerInvariant();
type = context.FindTypeIgnoreCase(name);
}
else
{
type = context.FindType(name);
}
if (type == null && context != universe.Mscorlib)
{
if (ignoreCase)
{
type = universe.Mscorlib.FindTypeIgnoreCase(name);
}
else
{
type = universe.Mscorlib.FindType(name);
}
}
if (type == null && resolve)
{
if (universe.Mscorlib.__IsMissing && !context.__IsMissing)
@ -499,11 +529,12 @@ namespace IKVM.Reflection
}
}
}
return Expand(type, context, throwOnError, originalName, resolve);
return Expand(type, context, throwOnError, originalName, resolve, ignoreCase);
}
internal Type Expand(Type type, Assembly context, bool throwOnError, string originalName, bool resolve)
internal Type Expand(Type type, Assembly context, bool throwOnError, string originalName, bool resolve, bool ignoreCase)
{
Debug.Assert(!resolve || !ignoreCase);
if (type == null)
{
if (throwOnError)
@ -519,7 +550,9 @@ namespace IKVM.Reflection
{
outer = type;
TypeName name = TypeName.Split(TypeNameParser.Unescape(nest));
type = outer.FindNestedType(name);
type = ignoreCase
? outer.FindNestedTypeIgnoreCase(name.ToLowerInvariant())
: outer.FindNestedType(name);
if (type == null)
{
if (resolve)
@ -542,7 +575,7 @@ namespace IKVM.Reflection
Type[] typeArgs = new Type[genericParameters.Length];
for (int i = 0; i < typeArgs.Length; i++)
{
typeArgs[i] = genericParameters[i].GetType(type.Assembly.universe, context, throwOnError, originalName, resolve);
typeArgs[i] = genericParameters[i].GetType(type.Assembly.universe, context, throwOnError, originalName, resolve, ignoreCase);
if (typeArgs[i] == null)
{
return null;

Просмотреть файл

@ -777,26 +777,40 @@ namespace IKVM.Reflection
{
// to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(),
// import that assembly and pass it as the context, but implicitly importing is considered evil
return GetType(null, assemblyQualifiedTypeName, false);
return GetType(null, assemblyQualifiedTypeName, false, false);
}
public Type GetType(string assemblyQualifiedTypeName, bool throwOnError)
{
// to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(),
// import that assembly and pass it as the context, but implicitly importing is considered evil
return GetType(null, assemblyQualifiedTypeName, throwOnError);
return GetType(null, assemblyQualifiedTypeName, throwOnError, false);
}
public Type GetType(string assemblyQualifiedTypeName, bool throwOnError, bool ignoreCase)
{
// to be more compatible with Type.GetType(), we could call Assembly.GetCallingAssembly(),
// import that assembly and pass it as the context, but implicitly importing is considered evil
return GetType(null, assemblyQualifiedTypeName, throwOnError, ignoreCase);
}
// note that context is slightly different from the calling assembly (System.Type.GetType),
// because context is passed to the AssemblyResolve event as the RequestingAssembly
public Type GetType(Assembly context, string assemblyQualifiedTypeName, bool throwOnError)
{
return GetType(context, assemblyQualifiedTypeName, throwOnError, false);
}
// note that context is slightly different from the calling assembly (System.Type.GetType),
// because context is passed to the AssemblyResolve event as the RequestingAssembly
public Type GetType(Assembly context, string assemblyQualifiedTypeName, bool throwOnError, bool ignoreCase)
{
TypeNameParser parser = TypeNameParser.Parse(assemblyQualifiedTypeName, throwOnError);
if (parser.Error)
{
return null;
}
return parser.GetType(this, context, throwOnError, assemblyQualifiedTypeName, false);
return parser.GetType(this, context, throwOnError, assemblyQualifiedTypeName, false, ignoreCase);
}
// this is similar to GetType(Assembly context, string assemblyQualifiedTypeName, bool throwOnError),
@ -809,7 +823,7 @@ namespace IKVM.Reflection
{
return null;
}
return parser.GetType(this, context, false, assemblyQualifiedTypeName, true);
return parser.GetType(this, context, false, assemblyQualifiedTypeName, true, false);
}
public Assembly[] GetAssemblies()