AttributedMetaType CreateInheritedType(Type root, Type type)
        {
            MetaType metaType;

            if (!this.types.TryGetValue(type, out metaType))
            {
                metaType = new AttributedMetaType(this.Model, this.Table, type, this);
                this.types.Add(type, metaType);

                if (type != root && type.BaseType != typeof(object))
                {
                    CreateInheritedType(root, type.BaseType);
                }
            }

            return((AttributedMetaType)metaType);
        }
        internal AttributedRootType(AttributedMetaModel model, AttributedMetaTable table, Type type)
            : base(model, table, type, null)
        {
            // check for inheritance and create all other types
            InheritanceMappingAttribute[] inheritanceInfo = (InheritanceMappingAttribute[])type.GetCustomAttributes(typeof(InheritanceMappingAttribute), true);

            if (inheritanceInfo.Length > 0)
            {
                if (this.Discriminator == null)
                {
                    throw Error.NoDiscriminatorFound(type);
                }

                if (!MappingSystem.IsSupportedDiscriminatorType(this.Discriminator.Type))
                {
                    throw Error.DiscriminatorClrTypeNotSupported(this.Discriminator.DeclaringType.Name, this.Discriminator.Name, this.Discriminator.Type);
                }

                this.types = new Dictionary <Type, MetaType>();
                this.types.Add(type, this); // add self
                this.codeMap = new Dictionary <object, MetaType>();

                // initialize inheritance types

                foreach (InheritanceMappingAttribute attr in inheritanceInfo)
                {
                    if (!type.IsAssignableFrom(attr.Type))
                    {
                        throw Error.InheritanceTypeDoesNotDeriveFromRoot(attr.Type, type);
                    }

                    if (attr.Type.IsAbstract)
                    {
                        throw Error.AbstractClassAssignInheritanceDiscriminator(attr.Type);
                    }

                    AttributedMetaType mt = this.CreateInheritedType(type, attr.Type);

                    if (attr.Code == null)
                    {
                        throw Error.InheritanceCodeMayNotBeNull();
                    }

                    if (mt.inheritanceCode != null)
                    {
                        throw Error.InheritanceTypeHasMultipleDiscriminators(attr.Type);
                    }

                    //object codeValue = DBConvert.ChangeType(*/attr.Code/*, this.Discriminator.Type);
                    object codeValue = attr.Code;

                    foreach (object d in codeMap.Keys)
                    {
                        // if the keys are equal, or if they are both strings containing only spaces
                        // they are considered equal

                        if ((codeValue.GetType() == typeof(string) &&
                             ((string)codeValue).Trim().Length == 0 &&
                             d.GetType() == typeof(string) &&
                             ((string)d).Trim().Length == 0) ||
                            object.Equals(d, codeValue))
                        {
                            throw Error.InheritanceCodeUsedForMultipleTypes(codeValue);
                        }
                    }

                    mt.inheritanceCode = codeValue;
                    this.codeMap.Add(codeValue, mt);

                    if (attr.IsDefault)
                    {
                        if (this.InheritanceDefault != null)
                        {
                            throw Error.InheritanceTypeHasMultipleDefaults(type);
                        }

                        this.InheritanceDefault = mt;
                    }
                }

                if (this.InheritanceDefault == null)
                {
                    throw Error.InheritanceHierarchyDoesNotDefineDefault(type);
                }
            }

            if (this.types != null)
            {
                this.InheritanceTypes = this.types.Values.ToList().AsReadOnly();
            }
            else
            {
                this.InheritanceTypes = new MetaType[] { this }.ToList().AsReadOnly();
            }

            Validate();
        }