Exemplo n.º 1
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        private FieldInfo FindBackingField(
            IPropertyBase property,
            IDictionary <Type, Dictionary <string, FieldInfo> > fieldCache)
        {
            var typesInHierarchy = property.DeclaringEntityType.ClrType.GetTypesInHierarchy().ToList();

            var fieldName = property["BackingField"] as string;

            if (fieldName != null)
            {
                foreach (var type in typesInHierarchy)
                {
                    var       fields = GetFields(type, fieldCache);
                    FieldInfo fieldInfo;
                    if (fields.TryGetValue(fieldName, out fieldInfo))
                    {
                        if (!fieldInfo.FieldType.GetTypeInfo().IsAssignableFrom(property.GetClrType().GetTypeInfo()))
                        {
                            throw new InvalidOperationException(
                                      CoreStrings.BadBackingFieldType(
                                          fieldName,
                                          fieldInfo.FieldType.ShortDisplayName(),
                                          property.DeclaringEntityType.DisplayName(),
                                          property.Name,
                                          property.GetClrType().ShortDisplayName()));
                        }

                        return(fieldInfo);
                    }
                }

                throw new InvalidOperationException(
                          CoreStrings.MissingBackingField(property.DeclaringEntityType.DisplayName(), property.Name, fieldName));
            }

            foreach (var type in typesInHierarchy)
            {
                var fields    = GetFields(type, fieldCache);
                var fieldInfo = _fieldMatcher.TryMatchFieldName(property, property.GetPropertyInfo(), fields);
                if (fieldInfo != null)
                {
                    return(fieldInfo);
                }
            }

            return(null);
        }
        // TODO: Consider doing this at model building time, but also consider mapping to interfaces
        // Issue #757
        public virtual IEnumerable <Tuple <IProperty, MemberInfo> > MapPropertiesToMembers(IEntityType entityType)
        {
            Check.NotNull(entityType, nameof(entityType));

            var fieldCache       = new Dictionary <Type, Dictionary <string, FieldInfo> >();
            var propertyMappings = new List <Tuple <IProperty, MemberInfo> >();

            foreach (var property in entityType.GetProperties().Where(p => !p.IsShadowProperty))
            {
                var propertyName = property.Name;

                MemberInfo memberInfo = null;
                foreach (var propertyInfo in entityType.ClrType.GetPropertiesInHierarchy(propertyName))
                {
                    // TODO: Handle cases where backing field is declared in a different class than the property
                    // Issue #758
                    Dictionary <string, FieldInfo> fields;
                    if (!fieldCache.TryGetValue(propertyInfo.DeclaringType, out fields))
                    {
                        fields = propertyInfo.DeclaringType.GetRuntimeFields().ToDictionary(f => f.Name);
                        fieldCache[propertyInfo.DeclaringType] = fields;
                    }

                    var fieldName = property["BackingField"] as string;
                    if (fieldName != null)
                    {
                        FieldInfo fieldInfo;
                        if (!fields.TryGetValue(fieldName, out fieldInfo))
                        {
                            throw new InvalidOperationException(Strings.MissingBackingField(entityType.Name, propertyName, fieldName));
                        }
                        if (!fieldInfo.FieldType.GetTypeInfo().IsAssignableFrom(property.ClrType.GetTypeInfo()))
                        {
                            throw new InvalidOperationException(
                                      Strings.BadBackingFieldType(fieldName, fieldInfo.FieldType.Name, entityType.Name, propertyName, property.ClrType.Name));
                        }
                        memberInfo = fieldInfo;
                    }
                    else
                    {
                        memberInfo = _fieldMatcher.TryMatchFieldName(property, propertyInfo, fields);
                    }

                    if (memberInfo != null)
                    {
                        break;
                    }
                }

                if (memberInfo == null)
                {
                    memberInfo = entityType.ClrType.GetPropertiesInHierarchy(propertyName).FirstOrDefault(p => p.SetMethod != null);
                }

                if (memberInfo == null)
                {
                    throw new InvalidOperationException(Strings.NoFieldOrSetter(entityType.Name, propertyName));
                }

                propertyMappings.Add(Tuple.Create(property, memberInfo));
            }

            return(propertyMappings);
        }