public static GenericDefinition Parse(string def, int start, int length) { int end = start + length; GenericDefinition ret = new GenericDefinition(); if (length == 0) { return(ret); } if (def[end - 1] == '>') { int descriptorEnd = def.IndexOf('<', start); string descriptor = def.Substring(start, descriptorEnd - start); ret.GenericTypeDefinition = GetTypeFromDescriptor(descriptor); start = descriptorEnd + 1; end = end - 1; length = end - start; } if (def[start] == '@') { string descriptor = def.Substring(start + 1, length - 1); ret.GenericInstanceType = GetTypeFromDescriptor(descriptor); } else if (length > 2 && def[start] == '!' && def[start + 1] == '!') { int genericParmIdx = int.Parse(def.Substring(2, length - 2)); ret.GenericParameter = genericParmIdx; } else { // must be generic arguments. List <GenericArgument> args = new List <GenericArgument>(); while (start < end) { int curEnd = FindNextComma(def, start, end); if (curEnd == start) { throw new Exception("definition syntax error"); } GenericArgument arg = new GenericArgument(); if (def[start] == '!') { arg.ContainingTypeArgumentIndex = int.Parse(def.Substring(start + 1, curEnd - start - 1)); } else if (def[start] == '{') { if (def[curEnd - 1] != '}') { throw new Exception("definition syntax error"); } arg.NestedType = Parse(def, start + 1, curEnd - 2 - start); } else { arg.FixedType = GetTypeFromDescriptor(def.Substring(start, curEnd - start)); } args.Add(arg); start = curEnd + 1; } ret.GenericArguments = args.ToArray(); } return(ret); }
public static Type ToGenericInstanceType(Type perceivedType, Type parentType, GenericDefinition m) { // is a specialized type defined? var genericInstanceType = m.GenericInstanceType; if (genericInstanceType != null) { return(genericInstanceType); } int genericParameter = -1; var genericArguments = m.GenericArguments; // is a generic type definition class defined? var genericTypeDef = m.GenericTypeDefinition; if (genericTypeDef == null) { genericTypeDef = perceivedType; genericParameter = m.GenericParameter; } // retrieve generic parameters if required. GenericTypeInfo parentGenericArguments = null; bool needParentGenericArguments = genericParameter >= 0 || genericArguments.Any(a => a.FixedType == null); if (needParentGenericArguments) { parentGenericArguments = GenericInstanceFactory.GetGenericTypeInfo(parentType); if (parentGenericArguments == null) { // Can either happen when the generics reflection annotations where not preserved // (i.e. a bug), when the user did not call GetTypeReflectionSafe() on an object, // or when requesting generics info not for an instance type, e.g. typeof(List<>). // As the second case can be difficult to debug, we emit a warning. TODO: we should // probably not emit a warning when the user code runs in release mode. Log.W("dot42", string.Format("Unable to reconstruct generic type definition for type {0}, parent type {1}. Did you use obj.GetTypeReflectionSafe()? If you are reflecting on an open generic type, i.e. typeof(List<>) you can ignore this warning.", perceivedType.FullName, parentType.FullName)); return(genericTypeDef); } } if (genericParameter != -1) { // ReSharper disable once PossibleNullReferenceException genericTypeDef = parentGenericArguments.GetGenericParameter(genericParameter); } if (genericArguments != null && genericArguments.Length > 0) { Type[] genericParameters = new Type[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; ++i) { Type resolvedArg; var arg = genericArguments[i]; if (arg.NestedType != null) { resolvedArg = ToGenericInstanceType(typeof(object), parentType, arg.NestedType); } else if (arg.FixedType != null) { resolvedArg = arg.FixedType; } else { // must be an index // ReSharper disable once PossibleNullReferenceException resolvedArg = parentGenericArguments.GetGenericParameter(arg.ContainingTypeArgumentIndex); } genericParameters[i] = resolvedArg; } return(GenericInstanceFactory.GetOrMakeGenericInstanceType(genericTypeDef, genericParameters)); } // return the type. return(genericTypeDef); }