Exemple #1
0
        private void AnalyzeFields()
        {
            IList relations = new ArrayList();
            var   fis       = this.classType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(fi => !fi.IsInitOnly);

            foreach (FieldInfo fi in fis)
            {
                string fname = fi.Name;
                if (fname.StartsWith("_ndo"))
                {
                    continue;
                }
                if (fi.FieldType.IsSubclassOf(typeof(System.Delegate)))
                {
                    continue;
                }

                object[] attributes = fi.GetCustomAttributes(false);
                bool     cont       = false;
                foreach (System.Attribute attr in attributes)
                {
                    if (attr is NDOTransientAttribute)
                    {
                        cont = true;
                        break;
                    }
                    if (attr is NDORelationAttribute)
                    {
                        this.relations.Add(new RelationNode(fi, (NDORelationAttribute)attr, this));
                        cont = true;
                        break;
                    }
                }
                if (cont)
                {
                    continue;
                }

                // Field type is persistent - assume relation with element multiplicity.
                if (typeof(IPersistenceCapable).IsAssignableFrom(fi.FieldType))
                {
                    NDORelationAttribute nra = new NDORelationAttribute(fi.FieldType, RelationInfo.Default);
                    this.relations.Add(new RelationNode(fi, nra, this));
                    continue;
                }

                // Field is a collection - assume that it is either a relation or a transient field.
                if (GenericIListReflector.IsGenericIList(fi.FieldType))
                {
                    if (typeof(IPersistenceCapable).IsAssignableFrom(fi.FieldType.GetGenericArguments()[0]))
                    {
                        NDORelationAttribute nra = new NDORelationAttribute(fi.FieldType.GetGenericArguments()[0], RelationInfo.Default);
                        this.relations.Add(new RelationNode(fi, nra, this));
                    }
                    else
                    {
                        Console.WriteLine("Warning: The field " + this.name + "." + fi.Name + " is a generic collection to a nonpersistent type. NDO assumes, that this field is transient.");
                    }
                    continue;
                }

                if (!fi.FieldType.IsGenericParameter && fi.FieldType.IsClass && fi.FieldType != typeof(string) && fi.FieldType != typeof(byte[]))
                {
                    this.embeddedTypes.Add(new EmbeddedTypeNode(fi));
                }
                else
                {
                    FieldNode fn = new FieldNode(fi);
                    this.fields.Add(fn);
                    Type ft = fi.FieldType;
                    if (ft.IsValueType && !ft.IsEnum && !StorableTypes.Contains(ft))
                    {
                        ValueTypes.Instance.Add(new ValueTypeNode(ft));
                    }
                }
            }

            // If there is more than one relation to the same target type
            // without relation name, assign a relation name automatically
            foreach (var group in this.relations.GroupBy(r => r.RelatedType))
            {
                if (group.Count() < 2)
                {
                    continue;
                }
                int countWithoutName = 0;
                foreach (var rel in group)
                {
                    if (string.IsNullOrEmpty(rel.RelationName))
                    {
                        if (countWithoutName > 0)
                        {
                            string relname = rel.Name;
                            if (relname[0] == '<')
                            {
                                int q = relname.IndexOf('>');
                                if (q == -1)
                                {
                                    q = relname.Length;
                                }
                                relname = relname.Substring(1, q - 1);
                            }
                            rel.RelationName = relname;
                        }
                        countWithoutName++;
                    }
                }
            }
        }
Exemple #2
0
        public RelationNode(FieldInfo relationFieldInfo, NDORelationAttribute attr, ClassNode parent)
        {
            this.parent    = parent;
            this.fieldType = relationFieldInfo.FieldType;
            Type            parentType   = relationFieldInfo.ReflectedType;
            NDOAssemblyName an           = new NDOAssemblyName(parentType.Assembly.FullName);
            string          assShortName = an.Name;

            this.isElement = !(relationFieldInfo.FieldType == typeof(IList) ||
                               relationFieldInfo.FieldType.GetInterface("IList") != null ||
                               GenericIListReflector.IsGenericIList(relationFieldInfo.FieldType));

            // dataType & declaringType always have
            // - a class/valutype prefix
            // - an [AssName] prefix
            this.dataType = new ReflectedType(relationFieldInfo.FieldType).ILName;
            if (relationFieldInfo.DeclaringType != relationFieldInfo.ReflectedType)
            {
                this.declaringType = new ReflectedType(relationFieldInfo.DeclaringType).ILName;
            }
            else
            {
                this.declaringType = null;
            }
            this.name = relationFieldInfo.Name;

            Type attrType = attr.GetType();

            this.relationName = attr.RelationName;
            this.relationInfo = attr.Info;
            Type relType;

            if (isElement)
            {
                relType = relationFieldInfo.FieldType;
            }
            else
            {
                if (attr.RelationType == null && relationFieldInfo.FieldType.IsGenericType)
                {
                    relType = relationFieldInfo.FieldType.GetGenericArguments()[0];
                }
                else
                {
                    relType = attr.RelationType;
                }

                if (relType == null)
                {
                    throw new Exception("Can't determine referenced type in relation " + parent.Name + "." + this.name + ". Provide a type parameter for the [NDORelation] attribute.");
                }
            }

            if (relType.IsGenericType && !relType.IsGenericTypeDefinition)
            {
                relType = relType.GetGenericTypeDefinition();
            }

            // Related Type hat kein "class " Prefix, hat [assName] nur bei fremden Assemblies.
            this.relatedType = new ReflectedType(relType, assShortName).ILNameWithoutPrefix;
            if (relType.IsGenericType)
            {
                this.relatedType = this.relatedType.Substring(0, this.relatedType.IndexOf('<'));
            }

            object[] attrs = relationFieldInfo.GetCustomAttributes(typeof(ForeignKeyColumnAttribute), true);
            if (attrs.Length > 0)
            {
                this.foreignKeyColumnAttributes = new ForeignKeyColumnAttribute[attrs.Length];
                attrs.CopyTo(this.foreignKeyColumnAttributes, 0);
            }
            attrs = relationFieldInfo.GetCustomAttributes(typeof(ChildForeignKeyColumnAttribute), true);
            if (attrs.Length > 0)
            {
                this.childForeignKeyColumnAttributes = new ChildForeignKeyColumnAttribute[attrs.Length];
                attrs.CopyTo(this.childForeignKeyColumnAttributes, 0);
            }
            attrs = relationFieldInfo.GetCustomAttributes(typeof(MappingTableAttribute), true);
            if (attrs.Length > 0)
            {
                MappingTableAttribute = (MappingTableAttribute)attrs[0];
            }
        }
Exemple #3
0
        void IFieldInitializer.InitFields()
        {
            bool isEnhancing = ((IEnhancerSupport)Parent.Parent).IsEnhancing;

            if (!isEnhancing)
            {
                GetOrdinal();
            }

            Class relatedClass = this.RelatedClass;

            Type t = Parent.SystemType;

            if (t == null)
            {
                throw new InternalException(1155, "Relation.InitFields");
            }

            FieldInfo fi = null;

            while (fi == null && t != typeof(object))
            {
                fi = t.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
                if (fi == null)
                {
                    t = t.BaseType;
                }
            }
            if (fi == null)
            {
                throw new NDOException(20, "Can't find field " + Parent.SystemType.Name + "." + FieldName);
            }

            FieldType = fi.FieldType;

            System.Attribute     a  = System.Attribute.GetCustomAttribute(fi, typeof(NDORelationAttribute), false);
            NDORelationAttribute ra = (NDORelationAttribute)a;

            this.composition = ra != null && (ra.Info & RelationInfo.Composite) != 0;

            if (fi.FieldType == typeof(System.Collections.IList) || fi.FieldType.GetInterface("IList") != null || fi.FieldType.FullName.StartsWith("System.Collections.Generic.IList`1"))
            {
                this.multiplicity = RelationMultiplicity.List;
            }
            else if (fi.FieldType.GetCustomAttributes(typeof(NDOPersistentAttribute), false).Length > 0)
            {
                this.multiplicity = RelationMultiplicity.Element;
            }
            else
            {
                throw new NDOException(111, "Invalid field type for relation " + t.FullName + "." + FieldName + ": Type = " + fi.FieldType.Name);
            }


            // This could be easier, if we hadn't the choice whether to use
            // polymorphy or not.
            bool cond1 = this.Multiplicity == RelationMultiplicity.Element &&
                         this.ForeignKeyTypeColumnName != null;
            bool cond2 = this.Multiplicity == RelationMultiplicity.List &&
                         this.MappingTable != null && this.MappingTable.ChildForeignKeyTypeColumnName != null;

            hasSubclasses = (relatedClass.HasSubclasses) &&
                            (cond1 || cond2);


            if (this.multiplicity == RelationMultiplicity.List)
            {
                if (ra == null)
                {
                    throw new NDOException(97, $"Can't determine relation type for relation {Parent.FullName}.{fi.Name}");
                }

                if (ra.RelationType == null && fi.FieldType.IsGenericType)
                {
                    this.referencedType = fi.FieldType.GetGenericArguments()[0];
                }
                else
                {
                    this.referencedType = ra.RelationType;
                }
                if (referencedType == null)
                {
                    throw new NDOException(101, "Can't determine referenced type in relation " + this.Parent.FullName + "." + this.fieldName + ". Provide a type parameter for the [NDORelation] attribute.");
                }
            }
            else
            {
                this.referencedType = FieldType;
            }

            if (HasSubclasses && Multiplicity == RelationMultiplicity.List && MappingTable == null)
            {
                //throw new NDOException(21, "Polymorphic 1:n-relation w/o mapping table is not supported");
                Debug.WriteLine("NDO Warning: Polymorphic 1:n-relation " + Parent.FullName + "." + this.FieldName + " w/o mapping table");
            }

            this.definingClass = this.Parent;
            Type bt = this.Parent.SystemType.BaseType;

            while (typeof(IPersistenceCapable).IsAssignableFrom(bt))
            {
                Class pcl = this.Parent.Parent.FindClass(bt);
                if (pcl.FindRelation(this.fieldName) != null)
                {
                    this.definingClass = pcl;
                }
                else
                {
                    break;
                }
                bt = bt.BaseType;
            }

            // Do not set fkColumn.Size to a value != 0 in during enhancing,
            // because that value would be hard coded into the mapping file.
            // Use (!isEnhancing) to make sure, that the code wasn't called  from the enhancer.
            if (this.MappingTable != null)
            {
                // r.ForeignKeyColumns points to the own table.
                if (Parent.Oid.OidColumns.Count != this.foreignKeyColumns.Count)
                {
                    throw new NDOException(115, "Column count between relation and Oid doesn't match. Type " + Parent.FullName + " has an oid column count of " + Parent.Oid.OidColumns.Count + ". The Relation " + Parent.FullName + "." + this.fieldName + " has a foreign key column count of " + this.foreignKeyColumns.Count + '.');
                }
                int i = 0;
                new ForeignKeyIterator(this).Iterate(delegate(ForeignKeyColumn fkColumn, bool isLastIndex)
                {
                    OidColumn oidColumn = (OidColumn)Parent.Oid.OidColumns[i];
                    if (!isEnhancing && fkColumn.Size == 0)
                    {
                        fkColumn.Size = oidColumn.Size;
                    }
                    fkColumn.SystemType = oidColumn.SystemType;
                    i++;
                }
                                                     );

                // r.MappingTable.ChildForeignKeyColumns points to the table of the related class.
                if (relatedClass.Oid.OidColumns.Count != this.mappingTable.ChildForeignKeyColumns.Count())
                {
                    throw new NDOException(115, "Column count between relation and Oid doesn't match. Type " + relatedClass.FullName + " has an oid column count of " + relatedClass.Oid.OidColumns.Count + ". The Relation " + this.Parent.FullName + "." + this.fieldName + " has a foreign key column count of " + this.mappingTable.ChildForeignKeyColumns.Count() + '.');
                }
                i = 0;
                new ForeignKeyIterator(this.mappingTable).Iterate(delegate(ForeignKeyColumn fkColumn, bool isLastIndex)
                {
                    OidColumn oidColumn = (OidColumn)relatedClass.Oid.OidColumns[i];
                    if (!isEnhancing && fkColumn.Size == 0)
                    {
                        fkColumn.Size = oidColumn.Size;
                    }
                    fkColumn.SystemType = oidColumn.SystemType;
                    i++;
                }
                                                                  );
            }
            else if (this.multiplicity == RelationMultiplicity.Element)  // The foreign key points to the tabel of the related class.
            {
                if (relatedClass.Oid.OidColumns.Count != this.foreignKeyColumns.Count)
                {
                    throw new NDOException(115, "Column count between relation and Oid doesn't match. Type " + relatedClass.FullName + " has an oid column count of " + relatedClass.Oid.OidColumns.Count + ". The Relation " + Parent.FullName + "." + this.fieldName + " has a foreign key column count of " + this.foreignKeyColumns.Count + '.');
                }
                int i = 0;
                new ForeignKeyIterator(this).Iterate(delegate(ForeignKeyColumn fkColumn, bool isLastIndex)
                {
                    OidColumn oidColumn = (OidColumn)relatedClass.Oid.OidColumns[i];
                    if (!isEnhancing && fkColumn.Size == 0)
                    {
                        fkColumn.Size = oidColumn.Size;
                    }
                    fkColumn.SystemType = oidColumn.SystemType;
                    i++;
                }
                                                     );
            }
            else  // List relation. The foreign key points to the own table.
            {
                if (Parent.Oid.OidColumns.Count != this.foreignKeyColumns.Count)
                {
                    throw new NDOException(115, "Column count between relation and Oid doesn't match. Type " + Parent.FullName + " has an oid column count of " + Parent.Oid.OidColumns.Count + ". The Relation " + Parent.FullName + "." + this.fieldName + " has a foreign key column count of " + this.foreignKeyColumns.Count + '.');
                }
                int i = 0;
                new ForeignKeyIterator(this).Iterate(delegate(ForeignKeyColumn fkColumn, bool isLastIndex)
                {
                    OidColumn oidColumn = (OidColumn)Parent.Oid.OidColumns[i];
                    if (!isEnhancing && fkColumn.Size == 0)
                    {
                        fkColumn.Size = oidColumn.Size;
                    }
                    fkColumn.SystemType = oidColumn.SystemType;
                    i++;
                }
                                                     );
            }
        }