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]; } }
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++; } } } }