Mono.CSharp.MetadataImporter.CreateType C# (CSharp) Method

CreateType() private method

private CreateType ( Type type, System.TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType ) : System.TypeSpec
type IKVM.Reflection.Type
declaringType System.TypeSpec
dtype DynamicTypeReader
canImportBaseType bool
return System.TypeSpec
        TypeSpec CreateType(MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType)
        {
            TypeSpec spec;
            if (import_cache.TryGetValue (type, out spec)) {
                if (spec == TypeManager.object_type) {
                    if (dtype.IsDynamicObject (this))
                        return InternalType.Dynamic;

                    return spec;
                }

                if (!spec.IsGeneric || type.IsGenericTypeDefinition)
                    return spec;

                if (!dtype.HasDynamicAttribute (this))
                    return spec;

                // We've found same object in the cache but this one has a dynamic custom attribute
                // and it's most likely dynamic version of same type IFoo<object> agains IFoo<dynamic>
                // Do type resolve process again in that case

                // TODO: Handle cases where they still unify
            }

            if (IsMissingType (type)) {
                spec = new TypeSpec (MemberKind.MissingType, declaringType, new ImportedTypeDefinition (type, this), type, Modifiers.PUBLIC);
                spec.MemberCache = MemberCache.Empty;
                import_cache.Add (type, spec);
                return spec;
            }

            if (type.IsGenericType && !type.IsGenericTypeDefinition) {
                var type_def = type.GetGenericTypeDefinition ();
                var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype);
                if (declaringType == null) {
                    // Simple case, no nesting
                    spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType);
                    spec = spec.MakeGenericType (module, targs);
                } else {
                    //
                    // Nested type case, converting .NET types like
                    // A`1.B`1.C`1<int, long, string> to typespec like
                    // A<int>.B<long>.C<string>
                    //
                    var nested_hierarchy = new List<TypeSpec> ();
                    while (declaringType.IsNested) {
                        nested_hierarchy.Add (declaringType);
                        declaringType = declaringType.DeclaringType;
                    }

                    int targs_pos = 0;
                    if (declaringType.Arity > 0) {
                        spec = declaringType.MakeGenericType (module, targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ());
                        targs_pos = spec.Arity;
                    } else {
                        spec = declaringType;
                    }

                    for (int i = nested_hierarchy.Count; i != 0; --i) {
                        var t = nested_hierarchy [i - 1];
                        spec = MemberCache.FindNestedType (spec, t.Name, t.Arity);
                        if (t.Arity > 0) {
                            spec = spec.MakeGenericType (module, targs.Skip (targs_pos).Take (spec.Arity).ToArray ());
                            targs_pos += t.Arity;
                        }
                    }

                    string name = type.Name;
                    int index = name.IndexOf ('`');
                    if (index > 0)
                        name = name.Substring (0, index);

                    spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos);
                    if (spec.Arity > 0) {
                        spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ());
                    }
                }

                // Don't add generic type with dynamic arguments, they can interfere with same type
                // using object type arguments
                if (!spec.HasDynamicElement) {

                    // Add to reading cache to speed up reading
                    if (!import_cache.ContainsKey (type))
                        import_cache.Add (type, spec);
                }

                return spec;
            }

            Modifiers mod;
            MemberKind kind;

            var ma = type.Attributes;
            switch (ma & TypeAttributes.VisibilityMask) {
            case TypeAttributes.Public:
            case TypeAttributes.NestedPublic:
                mod = Modifiers.PUBLIC;
                break;
            case TypeAttributes.NestedPrivate:
                mod = Modifiers.PRIVATE;
                break;
            case TypeAttributes.NestedFamily:
                mod = Modifiers.PROTECTED;
                break;
            case TypeAttributes.NestedFamORAssem:
                mod = Modifiers.PROTECTED | Modifiers.INTERNAL;
                break;
            default:
                mod = Modifiers.INTERNAL;
                break;
            }

            if ((ma & TypeAttributes.Interface) != 0) {
                kind = MemberKind.Interface;
            } else if (type.IsGenericParameter) {
                kind = MemberKind.TypeParameter;
            } else {
                var base_type = type.BaseType;
                if (base_type == null || (ma & TypeAttributes.Abstract) != 0) {
                    kind = MemberKind.Class;
                } else {
                    kind = DetermineKindFromBaseType (base_type);
                    if (kind == MemberKind.Struct || kind == MemberKind.Delegate) {
                        mod |= Modifiers.SEALED;
                    }
                }

                if (kind == MemberKind.Class) {
                    if ((ma & TypeAttributes.Sealed) != 0) {
                        mod |= Modifiers.SEALED;
                        if ((ma & TypeAttributes.Abstract) != 0)
                            mod |= Modifiers.STATIC;
                    } else if ((ma & TypeAttributes.Abstract) != 0) {
                        mod |= Modifiers.ABSTRACT;
                    }
                }
            }

            var definition = new ImportedTypeDefinition (type, this);
            TypeSpec pt;

            if (kind == MemberKind.Enum) {
                const BindingFlags underlying_member = BindingFlags.DeclaredOnly |
                    BindingFlags.Instance |
                    BindingFlags.Public | BindingFlags.NonPublic;

                var type_members = type.GetFields (underlying_member);
                foreach (var type_member in type_members) {
                    spec = new EnumSpec (declaringType, definition, CreateType (type_member.FieldType), type, mod);
                    break;
                }

                if (spec == null)
                    kind = MemberKind.Class;

            } else if (kind == MemberKind.TypeParameter) {
                spec = CreateTypeParameter (type, declaringType);
            } else if (type.IsGenericTypeDefinition) {
                definition.TypeParameters = CreateGenericParameters (type, declaringType);
            } else if (compiled_types.TryGetValue (type, out pt)) {
                //
                // Same type was found in inside compiled types. It's
                // either build-in type or forward referenced typed
                // which point into just compiled assembly.
                //
                spec = pt;
                BuildinTypeSpec bts = pt as BuildinTypeSpec;
                if (bts != null)
                    bts.SetDefinition (definition, type, mod);
            }

            if (spec == null)
                spec = new TypeSpec (kind, declaringType, definition, type, mod);

            import_cache.Add (type, spec);

            //
            // Two stage setup as the base type can be inflated declaring type or
            // another nested type inside same declaring type which has not been
            // loaded, therefore we can import a base type of nested types once
            // the types have been imported
            //
            if (canImportBaseType)
                ImportTypeBase (spec, type);

            return spec;
        }

Same methods

MetadataImporter::CreateType ( Type type ) : System.TypeSpec
MetadataImporter::CreateType ( Type type, DynamicTypeReader dtype, bool canImportBaseType ) : System.TypeSpec