Beispiel #1
0
        /// <summary>
        /// Invoked to update <see cref="VersionInfo"/>.
        /// </summary>
        /// <param name="changedEntity">The changed entity.</param>
        /// <param name="changedField">The changed field.</param>
        /// <returns>
        /// <see langword="True"/>, if <see cref="VersionInfo"/> was changed;
        /// otherwise, <see langword="false"/>.
        /// </returns>
        /// <exception cref="NotSupportedException">Version root can't implement
        /// <see cref="IHasVersionRoots"/>.</exception>
        protected internal bool UpdateVersionInfo(Entity changedEntity, FieldInfo changedField)
        {
            if (State.IsVersionInfoUpdated || IsRemoved || changedEntity.TypeInfo.IsSystem)
            {
                return(true);
            }
            bool changed = false;

            try {
                State.IsVersionInfoUpdated = true; // Prevents recursion
                if (!TypeInfo.HasVersionRoots)
                {
                    changed = SystemUpdateVersionInfo(changedEntity, changedField);
                }
                else
                {
                    foreach (var root in ((IHasVersionRoots)this).GetVersionRoots())
                    {
                        if (root.TypeInfo.HasVersionRoots)
                        {
                            throw new NotSupportedException(Strings.ExVersionRootObjectCantImplementIHasVersionRoots);
                        }
                        changed |= root.UpdateVersionInfo(changedEntity, changedField);
                    }
                }
                return(changed);
            }
            finally {
                State.IsVersionInfoUpdated = changed;
            }
        }
Beispiel #2
0
        /// <exception cref="ArgumentException"><paramref name="field"/> belongs to a different type.</exception>
        internal PersistentFieldState GetFieldState(FieldInfo field)
        {
            if (field.ReflectedType.IsInterface)
            {
                field = TypeInfo.FieldMap[field];
            }
            if (field.ReflectedType != TypeInfo)
            {
                throw new ArgumentException(Strings.ExFieldBelongsToADifferentType, "field");
            }
            var mappingInfo = field.MappingInfo;

            if (mappingInfo.Length == 0)
            {
                return(0); // EntitySet or another proxy
            }
            PersistentFieldState state = 0;
            var tuple = Tuple;

            if (tuple != null && tuple.AreAllColumnsAvalilable(mappingInfo))
            {
                state = PersistentFieldState.Loaded;
            }
            var diffTuple = tuple as DifferentialTuple;

            if (diffTuple != null && diffTuple.Difference.IsAtLeastOneColumAvailable(mappingInfo))
            {
                state = PersistentFieldState.Modified;
            }
            return(state);
        }
 protected override bool UpdateVersion(Entity changedEntity, M.FieldInfo changedField)
 {
     VersionId = new VersionStructure {
         Version = VersionId.Version + 1
     };
     return(true);
 }
Beispiel #4
0
        internal override sealed void EnsureIsFetched(FieldInfo field)
        {
            var state = State;

            if (state.PersistenceState == PersistenceState.New)
            {
                return;
            }

            var tuple = state.Tuple;

            // tuple is already cleared
            if (tuple == null && (Session.Configuration.Options & SessionOptions.ReadRemovedObjects) == SessionOptions.ReadRemovedObjects)
            {
                return;
            }

            if (tuple.GetFieldState(field.MappingInfo.Offset).IsAvailable())
            {
                return;
            }

            EnsureNotRemoved();
            Session.Handler.FetchField(Key, field);
        }
Beispiel #5
0
        private ColumnInfo BuildInheritedColumn(FieldInfo field, ColumnInfo ancestor)
        {
            var column = ancestor.Clone();

            column.Field                = field;
            column.Name                 = context.NameBuilder.BuildColumnName(field, ancestor);
            column.IsDeclared           = field.IsDeclared;
            column.IsPrimaryKey         = field.IsPrimaryKey;
            column.IsNullable           = field.IsNullable;
            column.IsSystem             = field.IsSystem;
            column.DefaultSqlExpression = field.DefaultSqlExpression;

            object defaultValue = null;

            if (field.IsEnum)
            {
                var underlyingType = Enum.GetUnderlyingType(field.ValueType.StripNullable());
                if (field.DefaultValue != null)
                {
                    defaultValue = Convert.ChangeType(field.DefaultValue, underlyingType);
                }
            }
            else
            {
                defaultValue = field.DefaultValue;
            }

            column.DefaultValue = defaultValue;

            return(column);
        }
        internal override sealed void SystemBeforeGetValue(FieldInfo field)
        {
            if (!Session.Configuration.Supports(SessionOptions.ReadRemovedObjects))
            {
                EnsureNotRemoved();
            }
            if (Session.IsDebugEventLoggingEnabled)
            {
                OrmLog.Debug(Strings.LogSessionXGettingValueKeyYFieldZ, Session, Key, field);
            }

            EnsureIsFetched(field);

            Session.SystemEvents.NotifyFieldValueGetting(this, field);
            using (Session.Operations.EnableSystemOperationRegistration()) {
                Session.Events.NotifyFieldValueGetting(this, field);

                if (Session.IsSystemLogicOnly)
                {
                    return;
                }

                var subscriptionInfo = GetSubscription(EntityEventBroker.GettingFieldEventKey);
                if (subscriptionInfo.Second != null)
                {
                    ((Action <Key, FieldInfo>)subscriptionInfo.Second)
                    .Invoke(subscriptionInfo.First, field);
                }
                OnGettingFieldValue(field);
            }
        }
Beispiel #7
0
 /// <summary>
 /// Builds the name for the <see cref="AssociationInfo"/>.
 /// </summary>
 /// <param name="ownerType">Type of the owner.</param>
 /// <param name="ownerField">The owner field.</param>
 /// <param name="targetType">Type of the target.</param>
 /// <returns>Association name.</returns>
 public string BuildAssociationName(TypeInfo ownerType, FieldInfo ownerField, TypeInfo targetType)
 {
     return(ApplyNamingRules(string.Format(AssociationPattern,
                                           ownerType.Name,
                                           ownerField.Name,
                                           targetType.Name)));
 }
 public override void TestFixtureSetUp()
 {
     base.TestFixtureSetUp();
     CustomerType         = Domain.Model.Types[typeof(Customer)];
     OrderType            = Domain.Model.Types[typeof(Order)];
     ProductType          = Domain.Model.Types[typeof(Product)];
     BookType             = Domain.Model.Types[typeof(Book)];
     TitleType            = Domain.Model.Types[typeof(Title)];
     ITitleType           = Domain.Model.Types[typeof(ITitle)];
     OfferContainerType   = Domain.Model.Types[typeof(OfferContainer)];
     PersonIdField        = Domain.Model.Types[typeof(Person)].Fields["Id"];
     OrderIdField         = Domain.Model.Types[typeof(Order)].Fields["Id"];
     CityField            = CustomerType.Fields["City"];
     AgeField             = Domain.Model.Types[typeof(AdvancedPerson)].Fields["Age"];
     CustomerField        = OrderType.Fields["Customer"];
     EmployeeField        = OrderType.Fields["Employee"];
     DetailsField         = OrderType.Fields["Details"];
     BooksField           = Domain.Model.Types[typeof(Author)].Fields["Books"];
     BookTitleField       = BookType.Fields["Title"];
     TitleBookField       = TitleType.Fields["Book"];
     LanguageField        = TitleType.Fields["Language"];
     TextField            = TitleType.Fields["Text"];
     GraphContainersField = typeof(PrefetchManager).GetField("graphContainers",
                                                             BindingFlags.NonPublic | BindingFlags.Instance);
     PrefetchProcessorField = typeof(SqlSessionHandler).GetField("prefetchManager",
                                                                 BindingFlags.NonPublic | BindingFlags.Instance);
     PrefetchTestHelper.FillDataBase(Domain);
 }
Beispiel #9
0
        internal override sealed void SystemSetValue(FieldInfo field, object oldValue, object newValue)
        {
            Session.SystemEvents.NotifyFieldValueSet(this, field, oldValue, newValue);
            using (Session.Operations.EnableSystemOperationRegistration()) {
                Session.Events.NotifyFieldValueSet(this, field, oldValue, newValue);

                if (Session.IsSystemLogicOnly)
                {
                    return;
                }

                if (CanBeValidated)
                {
                    Session.ValidationContext.RegisterForValidation(this, field);
                }

                var subscriptionInfo = GetSubscription(EntityEventBroker.SetFieldEventKey);
                if (subscriptionInfo.Second != null)
                {
                    ((Action <Key, FieldInfo, object, object>)subscriptionInfo.Second)
                    .Invoke(subscriptionInfo.First, field, oldValue, newValue);
                }
                NotifyFieldChanged(field);
                OnSetFieldValue(field, oldValue, newValue);
            }
        }
Beispiel #10
0
 internal override sealed void SystemSetValueCompleted(FieldInfo field, object oldValue, object newValue, Exception exception)
 {
     Session.SystemEvents.NotifyFieldValueSetCompleted(this, field, oldValue, newValue, exception);
     using (Session.Operations.EnableSystemOperationRegistration()) {
         Session.Events.NotifyFieldValueSetCompleted(this, field, oldValue, newValue, exception);
     }
 }
Beispiel #11
0
        internal override sealed void SystemBeforeSetValue(FieldInfo field, object value)
        {
            EnsureNotRemoved();

            if (!changeVersionOnSetAttempt)
            {
                UpdateVersionInfo(this, field);
            }


            Session.SystemEvents.NotifyFieldValueSetting(this, field, value);
            using (Session.Operations.EnableSystemOperationRegistration()) {
                Session.Events.NotifyFieldValueSetting(this, field, value);

                if (Session.IsSystemLogicOnly)
                {
                    return;
                }

                var subscriptionInfo = GetSubscription(EntityEventBroker.SettingFieldEventKey);
                if (subscriptionInfo.Second != null)
                {
                    ((Action <Key, FieldInfo, object>)subscriptionInfo.Second).Invoke(subscriptionInfo.First, field, value);
                }
                OnSettingFieldValue(field, value);
            }
        }
Beispiel #12
0
        internal override sealed void SystemSetValueAttempt(FieldInfo field, object value)
        {
            EnsureNotRemoved();

            OrmLog.Debug(Strings.LogSessionXSettingValueKeyYFieldZ, Session, Key, field);

            if (field.IsPrimaryKey)
            {
                throw new NotSupportedException(string.Format(Strings.ExUnableToSetKeyFieldXExplicitly, field.Name));
            }

            if (changeVersionOnSetAttempt)
            {
                UpdateVersionInfo(this, field);
            }

            Session.SystemEvents.NotifyFieldValueSettingAttempt(this, field, value);
            using (Session.Operations.EnableSystemOperationRegistration()) {
                Session.Events.NotifyFieldValueSettingAttempt(this, field, value);

                if (Session.IsSystemLogicOnly)
                {
                    return;
                }

                var subscriptionInfo = GetSubscription(EntityEventBroker.SettingFieldAttemptEventKey);
                if (subscriptionInfo.Second != null)
                {
                    ((Action <Key, FieldInfo, object>)subscriptionInfo.Second).Invoke(subscriptionInfo.First, field, value);
                }
                OnSettingFieldValueAttempt(field, value);
                Session.ValidationContext.ValidateSetAttempt(this, field, value);
            }
        }
Beispiel #13
0
        internal override sealed void SystemBeforeGetValue(FieldInfo field)
        {
            if (!Session.Configuration.Supports(SessionOptions.ReadRemovedObjects))
            {
                EnsureNotRemoved();
            }

            // getting of field value is frequent operation and access to resources
            // will slow down execution significantly
            if (OrmLog.IsLogged(LogLevel.Debug))
            {
                OrmLog.Debug(Strings.LogSessionXGettingValueKeyYFieldZ, Session, Key, field);
            }

            EnsureIsFetched(field);

            Session.SystemEvents.NotifyFieldValueGetting(this, field);
            using (Session.Operations.EnableSystemOperationRegistration()) {
                Session.Events.NotifyFieldValueGetting(this, field);

                if (Session.IsSystemLogicOnly)
                {
                    return;
                }

                var subscriptionInfo = GetSubscription(EntityEventBroker.GettingFieldEventKey);
                if (subscriptionInfo.Second != null)
                {
                    ((Action <Key, FieldInfo>)subscriptionInfo.Second)
                    .Invoke(subscriptionInfo.First, field);
                }
                OnGettingFieldValue(field);
            }
        }
Beispiel #14
0
 /// <summary>
 /// Builds foreign key name by association.
 /// </summary>
 /// <returns>Foreign key name.</returns>
 public string BuildReferenceForeignKeyName(TypeInfo ownerType, FieldInfo ownerField, TypeInfo targetType)
 {
     ArgumentValidator.EnsureArgumentNotNull(ownerType, "ownerType");
     ArgumentValidator.EnsureArgumentNotNull(ownerField, "ownerField");
     ArgumentValidator.EnsureArgumentNotNull(targetType, "targetType");
     return(ApplyNamingRules(string.Format(ReferenceForeignKeyFormat, ownerType.Name, ownerField.Name, targetType.Name)));
 }
        // Constructors

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="owner">Persistent this entity set belongs to.</param>
        /// <param name="field">Field corresponds to this entity set.</param>
        protected EntitySetBase(Entity owner, FieldInfo field)
            : base(owner.Session)
        {
            this.owner = owner;
            Field      = field;
            State      = new EntitySetState(this);
            var association = Field.Associations.Last();

            if (association.AuxiliaryType != null && association.IsMaster)
            {
                Domain domain   = Session.Domain;
                var    itemType = domain.Model.Types[Field.ItemType];
                auxilaryTypeKeyTransform = new CombineTransform(
                    false,
                    owner.TypeInfo.Key.TupleDescriptor,
                    itemType.Key.TupleDescriptor);
            }

            if (association.Multiplicity != Multiplicity.ManyToOne && association.Multiplicity != Multiplicity.OneToMany)
            {
                skipOwnerVersionChange = false;
            }
            else
            {
                skipOwnerVersionChange = Session.Domain.Configuration.VersioningConvention.DenyEntitySetOwnerVersionChange;
            }

            Initialize(WellKnownOrmTypes.EntitySetBase);
        }
Beispiel #16
0
 protected bool IsFieldAvailable(FieldInfo field)
 {
     if (field.ReflectedType.IsInterface)
     {
         field = TypeInfo.FieldMap[field];
     }
     return(Tuple.GetFieldState(field.MappingInfo.Offset).IsAvailable());
 }
Beispiel #17
0
 internal FieldAccessor <T> GetFieldAccessor <T>(FieldInfo field)
 {
     if (field.ReflectedType.IsInterface)
     {
         field = TypeInfo.FieldMap[field];
     }
     return((FieldAccessor <T>)field.ReflectedType.Accessors.GetFieldAccessor(field));
 }
Beispiel #18
0
 /// <summary>
 /// Called to update the fields describing <see cref="Entity"/>'s version.
 /// </summary>
 /// <param name="changedEntity">The changed entity.</param>
 /// <param name="changedField">The changed field.</param>
 /// <returns>
 /// <see langword="True"/>, if <see cref="VersionInfo"/> was changed;
 /// otherwise, <see langword="false"/>.
 /// </returns>
 protected virtual bool UpdateVersion(Entity changedEntity, FieldInfo changedField)
 {
     foreach (var field in TypeInfo.GetVersionFields().Where(f => f.AutoVersion))
     {
         SetFieldValue(field, VersionGenerator.GenerateNextVersion(GetFieldValue(field)));
     }
     return(true);
 }
Beispiel #19
0
 /// <summary>
 /// Sets the field value.
 /// Field value type must be specified precisely.
 /// E.g. usage of <see cref="Object"/> instead of <see cref="IEntity"/> might lead to unpredictable effects.
 /// </summary>
 /// <typeparam name="T">Field value type.</typeparam>
 /// <param name="field">The field.</param>
 /// <param name="value">The value to set.</param>
 protected internal void SetFieldValue <T>(FieldInfo field, T value)
 {
     if (field.ReflectedType.IsInterface)
     {
         field = TypeInfo.FieldMap[field];
     }
     SetFieldValue(field, (object)value);
 }
Beispiel #20
0
        /// <summary>
        /// Gets the name for <see cref="ColumnInfo"/> object.
        /// </summary>
        /// <param name="field">The field info.</param>
        /// <param name="baseColumn">The <see cref="ColumnInfo"/> object.</param>
        /// <returns>Column name.</returns>
        public string BuildColumnName(FieldInfo field, ColumnInfo baseColumn)
        {
            ArgumentValidator.EnsureArgumentNotNull(field, "field");
            ArgumentValidator.EnsureArgumentNotNull(baseColumn, "baseColumn");

            var result = field.MappingName ?? field.Name;

            return(ApplyNamingRules(result));
        }
        internal static void ValidateLoadedEntitySet(Key key, FieldInfo field, int count, bool isFullyLoaded,
                                                     Session session)
        {
            EntitySetState state;

            Assert.IsTrue(session.Handler.LookupState(key, field, out state));
            Assert.AreEqual(count, state.Count());
            Assert.AreEqual(isFullyLoaded, state.IsFullyLoaded);
        }
Beispiel #22
0
 private static Expression BuildExpressionForFieldRecursivly(FieldInfo field, Expression parameter)
 {
     if (field.IsNested)
     {
         var expression = BuildExpressionForFieldRecursivly(field.Parent, parameter);
         return(Expression.Property(expression, field.DeclaringField.UnderlyingProperty));
     }
     return(Expression.Property(parameter, field.DeclaringField.UnderlyingProperty));
 }
    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);
        }
      }
    }
            // Constructors

            public CacheKey(FieldInfo referencingField, int?itemCountLimit)
            {
                this.ReferencingField = referencingField;
                this.ItemCountLimit   = itemCountLimit;
                unchecked {
                    cachedHashCode = (ReferencingField.GetHashCode() * 397)
                                     ^ (ItemCountLimit.HasValue ? 1 : 0);
                }
            }
        private Expression BuildFieldAccess(FieldInfo field, bool addNullability)
        {
            var fieldIndex = usedFields.Count;
            var valueType  = addNullability ? field.ValueType.ToNullable() : field.ValueType;

            usedFields.Add(field);
            return(Expression.Call(parameter,
                                   WellKnownMembers.Tuple.GenericAccessor.MakeGenericMethod(valueType),
                                   Expression.Constant(fieldIndex)));
        }
Beispiel #26
0
        private static FieldAccessor CreateFieldAccessor(Type accessorType, FieldInfo field)
        {
            var accessor = (FieldAccessor)
                           System.Activator.CreateInstance(
                accessorType.MakeGenericType(field.ValueType),
                BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
                null, ArrayUtils <object> .EmptyArray, null);

            accessor.Field = field;
            return(accessor);
        }
        private void EnsureCanBeUsedInFilter(Expression expression, FieldInfo field)
        {
            var canBeUsed = field.ReflectedType == field.DeclaringType ||
                            field.IsPrimaryKey ||
                            field.DeclaringType.Hierarchy.InheritanceSchema != InheritanceSchema.ClassTable;

            if (!canBeUsed)
            {
                throw UnableToTranslate(expression, string.Format(Strings.FieldXDoesNotExistInTableForY, field.Name, field.ReflectedType));
            }
        }
Beispiel #28
0
        /// <summary>
        /// Gets the key of the entity, that is referenced by specified field
        /// of the target persistent object.
        /// </summary>
        /// <remarks>
        /// Result is the same as <c>GetValue&lt;Entity&gt;(field).Key</c>,
        /// but referenced entity will not be materialized.
        /// </remarks>
        /// <param name="field">The reference field. Field value type must be
        /// <see cref="Entity"/> descendant.</param>
        /// <returns>Referenced entity key.</returns>
        /// <exception cref="InvalidOperationException">Field is not a reference field.</exception>
        protected internal Key GetReferenceKey(FieldInfo field)
        {
            Key key = null;

            try {
                if (field.ReflectedType.IsInterface)
                {
                    field = TypeInfo.FieldMap[field];
                }
                SystemBeforeGetValue(field);
                if (!field.IsEntity)
                {
                    throw new InvalidOperationException(
                              String.Format(Strings.ExFieldIsNotAnEntityField, field.Name, field.ReflectedType.Name));
                }

                var types = Session.Domain.Model.Types;
                var type  = types[field.ValueType];
                var tuple = Tuple;
                if (tuple.ContainsEmptyValues(field.MappingInfo))
                {
                    return(null);
                }

                int typeIdColumnIndex = type.Key.TypeIdColumnIndex;
                var accuracy          = TypeReferenceAccuracy.BaseType;
                if (typeIdColumnIndex >= 0)
                {
                    accuracy = TypeReferenceAccuracy.ExactType;
                }
                var keyValue = field.ExtractValue(tuple);
                if (accuracy == TypeReferenceAccuracy.ExactType)
                {
                    int typeId = keyValue.GetValueOrDefault <int>(typeIdColumnIndex);
                    if (typeId != TypeInfo.NoTypeId) // != default(int) != 0
                    {
                        type = types[typeId];
                    }
                    else
                    {
                        // This may happen if reference is null
                        accuracy = TypeReferenceAccuracy.BaseType;
                    }
                }
                key = Key.Create(Session.Domain, Session.StorageNodeId, type, accuracy, keyValue);
                SystemGetValue(field, key);
                SystemGetValueCompleted(field, key, null);
                return(key);
            }
            catch (Exception e) {
                SystemGetValueCompleted(field, key, e);
                throw;
            }
        }
Beispiel #29
0
        /// <summary>
        /// Builds the <see cref="MappedNode.MappingName"/>.
        /// </summary>
        /// <param name="complexField">The complex field.</param>
        /// <param name="childField">The child field.</param>
        /// <returns>Field mapping name.</returns>
        public string BuildMappingName(FieldInfo complexField, FieldInfo childField)
        {
            Func <FieldInfo, string> getMappingName = f => f.MappingName ?? f.Name;
            var nameSource = complexField;

            while (nameSource.Parent != null)
            {
                nameSource = nameSource.Parent;
            }
            return(string.Concat(getMappingName(nameSource), ".", getMappingName(childField)));
        }
Beispiel #30
0
        /// <summary>
        /// Builds the full name of the <paramref name="childField"/>.
        /// </summary>
        /// <param name="complexField">The complex field.</param>
        /// <param name="childField">The child field.</param>
        /// <returns>Nested field name.</returns>
        public string BuildNestedFieldName(FieldInfo complexField, FieldInfo childField)
        {
            ArgumentValidator.EnsureArgumentNotNull(complexField, "complexField");
            ArgumentValidator.EnsureArgumentNotNull(childField, "childField");
            var nameSource = complexField;

            while (nameSource.Parent != null)
            {
                nameSource = nameSource.Parent;
            }
            return(string.Concat(nameSource.Name, ".", childField.Name));
        }