Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }