private void BuildNestedFields(FieldInfo source, FieldInfo target, IEnumerable<FieldInfo> fields)
    {
      var buffer = fields.ToList();

      foreach (var field in buffer) {
        var clone = field.Clone();
        if (target.SkipVersion)
          clone.SkipVersion = true;
        clone.IsSystem = false;
        clone.IsLazyLoad = field.IsLazyLoad || target.IsLazyLoad;
        if (target.IsDeclared) {
          clone.Name = context.NameBuilder.BuildNestedFieldName(target, field);
          clone.OriginalName = field.OriginalName;
          // One-field reference
          if (target.IsEntity && buffer.Count == 1) {
            clone.MappingName = target.MappingName;
            clone.DefaultValue = target.DefaultValue;
          }
          else
            clone.MappingName = context.NameBuilder.BuildMappingName(target, field);
        }
        if (target.Fields.Contains(clone.Name))
          continue;
        clone.Parent = target;
        target.ReflectedType.Fields.Add(clone);

        if (field.IsStructure || field.IsEntity) {
          BuildNestedFields(source, clone, field.Fields);
          foreach (FieldInfo clonedFields in clone.Fields)
            target.Fields.Add(clonedFields);
        }
        else {
          if (field.Column!=null)
            clone.Column = BuildInheritedColumn(clone, field.Column);
        }
        if (target.IsStructure && clone.IsEntity && !IsAuxiliaryType(clone.ReflectedType)) {
          var origin = context.Model.Associations
            .Find(context.Model.Types[field.ValueType], true)
            .FirstOrDefault(a => a.OwnerField.Equals(field));
          if (origin!=null && !clone.IsInherited) {
            AssociationBuilder.BuildAssociation(context, origin, clone);
            context.DiscardedAssociations.Add(origin);
          }
        }
        if (!clone.IsStructure && !clone.IsEntitySet && !target.ReflectedType.IsInterface && 0!=(clone.Attributes & FieldAttributes.Indexed)) {
          var typeDef = context.ModelDef.Types[target.DeclaringType.UnderlyingType];
          var attribute = new IndexAttribute(clone.Name);
          var index = context.ModelDefBuilder.DefineIndex(typeDef, attribute);
          if (typeDef.Indexes.Contains(index.Name))
            throw new DomainBuilderException(
              string.Format(Strings.ExIndexWithNameXIsAlreadyRegistered, index.Name));

          typeDef.Indexes.Add(index);
          BuildLog.Info(Strings.LogIndexX, index.Name);
        }
      }
    }
Esempio n. 2
0
        private FieldInfo BuildDeclaredField(TypeInfo type, FieldDef fieldDef)
        {
            BuildLog.Info(Strings.LogBuildingDeclaredFieldXY, type.Name, fieldDef.Name);

            var fieldInfo = new FieldInfo(type, fieldDef.Attributes)
            {
                UnderlyingProperty = fieldDef.UnderlyingProperty,
                Name         = fieldDef.Name,
                OriginalName = fieldDef.Name,
                MappingName  = fieldDef.MappingName,
                ValueType    = fieldDef.ValueType,
                ItemType     = fieldDef.ItemType,
                Length       = fieldDef.Length,
                Scale        = fieldDef.Scale,
                Precision    = fieldDef.Precision,
                Validators   = fieldDef.Validators,
            };

            if (fieldInfo.IsStructure && DeclaresOnValidate(fieldInfo.ValueType))
            {
                fieldInfo.Validators.Add(new StructureFieldValidator());
            }

            if (fieldInfo.IsEntitySet && DeclaresOnValidate(fieldInfo.ValueType))
            {
                fieldInfo.Validators.Add(new EntitySetFieldValidator());
            }

            type.Fields.Add(fieldInfo);

            if (fieldInfo.IsEntitySet)
            {
                AssociationBuilder.BuildAssociation(context, fieldDef, fieldInfo);
                return(fieldInfo);
            }

            if (fieldInfo.IsEntity)
            {
                var fields = context.Model.Types[fieldInfo.ValueType].Fields.Where(f => f.IsPrimaryKey);
                // Adjusting default value if any
                if (fields.Count() == 1 && fieldDef.DefaultValue != null)
                {
                    fieldInfo.DefaultValue =
                        ValueTypeBuilder.AdjustValue(fieldInfo, fields.First().ValueType, fieldDef.DefaultValue);
                }

                BuildNestedFields(null, fieldInfo, fields);

                if (!IsAuxiliaryType(type))
                {
                    AssociationBuilder.BuildAssociation(context, fieldDef, fieldInfo);
                    if (type.IsStructure)
                    {
                        fieldInfo.Associations.ForEach(a => context.DiscardedAssociations.Add(a));
                    }
                }

                // Adjusting type discriminator field for references
                if (fieldDef.IsTypeDiscriminator)
                {
                    type.Hierarchy.TypeDiscriminatorMap.Field = fieldInfo.Fields.First();
                }
            }

            if (fieldInfo.IsStructure)
            {
                BuildNestedFields(null, fieldInfo, context.Model.Types[fieldInfo.ValueType].Fields);
                var structureFullTextIndex = context.ModelDef.FullTextIndexes.TryGetValue(fieldInfo.ValueType);
                if (structureFullTextIndex != null)
                {
                    var hierarchyTypeInfo = context.Model.Types[fieldInfo.DeclaringType.UnderlyingType];
                    var structureTypeInfo = context.Model.Types[fieldInfo.ValueType];
                    var currentIndex      = context.ModelDef.FullTextIndexes.TryGetValue(hierarchyTypeInfo.UnderlyingType);
                    if (currentIndex == null)
                    {
                        currentIndex = new FullTextIndexDef(context.ModelDef.Types.TryGetValue(type.UnderlyingType));
                        context.ModelDef.FullTextIndexes.Add(currentIndex);
                    }

                    currentIndex.Fields.AddRange(structureFullTextIndex.Fields
                                                 .Select(f => new {
                        fieldInfo.DeclaringType
                        .StructureFieldMapping[new Pair <FieldInfo>(fieldInfo, structureTypeInfo.Fields[f.Name])].Name,
                        f.IsAnalyzed,
                        f.Configuration,
                        f.TypeFieldName
                    })
                                                 .Select(g => new FullTextFieldDef(g.Name, g.IsAnalyzed)
                    {
                        Configuration = g.Configuration, TypeFieldName = g.TypeFieldName
                    }));
                }
            }

            if (fieldInfo.IsPrimitive)
            {
                fieldInfo.DefaultValue         = fieldDef.DefaultValue;
                fieldInfo.DefaultSqlExpression = fieldDef.DefaultSqlExpression;
                fieldInfo.Column = BuildDeclaredColumn(fieldInfo);
                if (fieldDef.IsTypeDiscriminator)
                {
                    type.Hierarchy.TypeDiscriminatorMap.Field = fieldInfo;
                }
            }

            return(fieldInfo);
        }