private FieldInfo GetFieldToSet(IConventionPropertyBase propertyBase)
        {
            if (propertyBase == null ||
                !ConfigurationSource.Convention.Overrides(propertyBase.GetFieldInfoConfigurationSource()))
            {
                return(null);
            }

            var type = propertyBase.DeclaringType.ClrType;

            while (type != null)
            {
                var fieldInfo = TryMatchFieldName(
                    propertyBase.DeclaringType.Model, type, propertyBase.ClrType, propertyBase.Name);
                if (fieldInfo != null &&
                    (propertyBase.PropertyInfo != null || propertyBase.Name == fieldInfo.GetSimpleMemberName()))
                {
                    return(fieldInfo);
                }

                type = type.GetTypeInfo().BaseType;
            }

            return(null);
        }
 /// <summary>
 ///     Sets the <see cref="PropertyAccessMode" /> to use for this property.
 /// </summary>
 /// <param name="property"> The property for which to set the access mode. </param>
 /// <param name="propertyAccessMode"> The <see cref="PropertyAccessMode" />, or null to clear the mode set.</param>
 /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
 public static void SetPropertyAccessMode(
     [NotNull] this IConventionPropertyBase property,
     PropertyAccessMode?propertyAccessMode,
     bool fromDataAnnotation = false)
 => Check.NotNull(property, nameof(property)).AsPropertyBase()
 .SetPropertyAccessMode(
     propertyAccessMode, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention);
Example #3
0
        private FieldInfo GetFieldToSet(IConventionPropertyBase propertyBase)
        {
            if (propertyBase == null ||
                !ConfigurationSource.Convention.Overrides(propertyBase.GetFieldInfoConfigurationSource()) ||
                propertyBase.IsIndexerProperty() ||
                propertyBase.IsShadowProperty())
            {
                return(null);
            }

            var entityType = (IConventionEntityType)propertyBase.DeclaringType;
            var type       = entityType.ClrType;
            var baseTypes  = entityType.GetAllBaseTypes().ToArray();

            while (type != null)
            {
                var fieldInfo = TryMatchFieldName(propertyBase, entityType, type);
                if (fieldInfo != null &&
                    (propertyBase.PropertyInfo != null || propertyBase.Name == fieldInfo.GetSimpleMemberName()))
                {
                    return(fieldInfo);
                }

                type       = type.BaseType;
                entityType = baseTypes.FirstOrDefault(et => et.ClrType == type);
            }

            return(null);
        }
Example #4
0
        /// <summary>
        ///     Sets the <see cref="PropertyAccessMode" /> to use for this property.
        /// </summary>
        /// <param name="property"> The property for which to set the access mode. </param>
        /// <param name="propertyAccessMode"> The <see cref="PropertyAccessMode" />, or null to clear the mode set.</param>
        /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
        public static void SetPropertyAccessMode(
            [NotNull] this IConventionPropertyBase property,
            PropertyAccessMode?propertyAccessMode,
            bool fromDataAnnotation = false)
        {
            Check.NotNull(property, nameof(property));

            property.SetAnnotation(CoreAnnotationNames.PropertyAccessMode, propertyAccessMode, fromDataAnnotation);
        }
Example #5
0
        private static FieldInfo?TryMatchFieldName(
            IConventionPropertyBase propertyBase,
            IConventionEntityType?entityType,
            Type entityClrType)
        {
            var propertyName = propertyBase.Name;

            IReadOnlyDictionary <string, FieldInfo> fields;

            if (entityType == null)
            {
                var newFields = new Dictionary <string, FieldInfo>(StringComparer.Ordinal);
                foreach (var field in entityClrType.GetRuntimeFields())
                {
                    if (!field.IsStatic &&
                        !newFields.ContainsKey(field.Name))
                    {
                        newFields[field.Name] = field;
                    }
                }

                fields = newFields;
            }
            else
            {
                fields = entityType.GetRuntimeFields();
            }

            var sortedFields = fields.OrderBy(p => p.Key, StringComparer.Ordinal).ToArray();

            var match = TryMatch(sortedFields, "<", propertyName, ">k__BackingField", null, null, entityClrType, propertyName);

            if (match == null)
            {
                match = TryMatch(sortedFields, propertyName, "", "", propertyBase, null, entityClrType, propertyName);

                var camelPrefix     = char.ToLowerInvariant(propertyName[0]).ToString();
                var camelizedSuffix = propertyName.Substring(1);

                match = TryMatch(sortedFields, camelPrefix, camelizedSuffix, "", propertyBase, match, entityClrType, propertyName);
                match = TryMatch(sortedFields, "_", camelPrefix, camelizedSuffix, propertyBase, match, entityClrType, propertyName);
                match = TryMatch(sortedFields, "_", "", propertyName, propertyBase, match, entityClrType, propertyName);
                match = TryMatch(sortedFields, "m_", camelPrefix, camelizedSuffix, propertyBase, match, entityClrType, propertyName);
                match = TryMatch(sortedFields, "m_", "", propertyName, propertyBase, match, entityClrType, propertyName);
                match = TryMatch(sortedFields, "", camelPrefix + camelizedSuffix, "_", propertyBase, match, entityClrType, propertyName);
            }

            return(match);
        }
 /// <summary>
 ///     Returns the configuration source for <see cref="PropertyBaseExtensions.GetPropertyAccessMode" />.
 /// </summary>
 /// <param name="property"> The property to find configuration source for. </param>
 /// <returns> The configuration source for <see cref="PropertyBaseExtensions.GetPropertyAccessMode" />. </returns>
 public static ConfigurationSource?GetPropertyAccessModeConfigurationSource([NotNull] this IConventionPropertyBase property)
 => property.FindAnnotation(CoreAnnotationNames.PropertyAccessMode)?.GetConfigurationSource();
 /// <summary>
 ///     <para>
 ///         Sets the underlying CLR field that this property should use.
 ///         This may be <c>null</c> for shadow properties or if the backing field for the property is not known.
 ///     </para>
 ///     <para>
 ///         Backing fields are normally found by convention as described
 ///         here: http://go.microsoft.com/fwlink/?LinkId=723277.
 ///         This method is useful for setting backing fields explicitly in cases where the
 ///         correct field is not found by convention.
 ///     </para>
 ///     <para>
 ///         By default, the backing field, if one is found or has been specified, is used when
 ///         new objects are constructed, typically when entities are queried from the database.
 ///         Properties are used for all other accesses. This can be changed by calling
 ///         <see cref="SetPropertyAccessMode" />.
 ///     </para>
 /// </summary>
 /// <param name="property"> The property for which the backing field should be set. </param>
 /// <param name="fieldName"> The name of the field to use. </param>
 /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
 public static void SetField(
     [NotNull] this IConventionPropertyBase property,
     [CanBeNull] string fieldName,
     bool fromDataAnnotation = false)
 => Check.NotNull(property, nameof(property)).AsPropertyBase()
 .SetField(fieldName, fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention);
Example #8
0
        private static FieldInfo TryMatch(
            KeyValuePair <string, FieldInfo>[] array,
            string prefix,
            string middle,
            string suffix,
            IConventionPropertyBase propertyBase,
            FieldInfo existingMatch,
            Type entityClrType,
            string propertyName)
        {
            var index = PrefixBinarySearch(array, prefix, 0, array.Length - 1);

            if (index == -1)
            {
                return(existingMatch);
            }

            var typeInfo     = propertyBase?.ClrType;
            var length       = prefix.Length + middle.Length + suffix.Length;
            var currentValue = array[index];

            while (true)
            {
                if (currentValue.Key.Length == length &&
                    currentValue.Key.EndsWith(suffix, StringComparison.Ordinal) &&
                    currentValue.Key.IndexOf(middle, prefix.Length, StringComparison.Ordinal) == prefix.Length)
                {
                    var newMatch = typeInfo == null
                        ? currentValue.Value
                        : (typeInfo.IsCompatibleWith(currentValue.Value.FieldType)
                            ? currentValue.Value
                            : null);

                    if (newMatch != null)
                    {
                        if (existingMatch != null &&
                            newMatch != existingMatch)
                        {
                            propertyBase.SetOrRemoveAnnotation(
                                CoreAnnotationNames.AmbiguousField,
                                CoreStrings.ConflictingBackingFields(
                                    propertyName, entityClrType.ShortDisplayName(), existingMatch.Name, newMatch.Name));
                            return(null);
                        }

                        return(newMatch);
                    }

                    return(existingMatch);
                }

                if (++index == array.Length)
                {
                    return(existingMatch);
                }

                currentValue = array[index];
                if (!currentValue.Key.StartsWith(prefix, StringComparison.Ordinal))
                {
                    return(existingMatch);
                }
            }
        }