コード例 #1
0
        // TODO: Consider doing this at model building time, but also consider mapping to interfaces
        public virtual IEnumerable <Tuple <IProperty, MemberInfo> > MapPropertiesToMembers([NotNull] IEntityType entityType)
        {
            Check.NotNull(entityType, "entityType");

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

            foreach (var property in entityType.Properties.Where(p => p.IsClrProperty))
            {
                var propertyName = property.Name;

                MemberInfo memberInfo = null;
                foreach (var propertyInfo in entityType.Type.GetPropertiesInHierarchy(propertyName))
                {
                    // TODO: Handle cases where backing field is declared in a different class than the property
                    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"];
                    if (fieldName != null)
                    {
                        FieldInfo fieldInfo;
                        if (!fields.TryGetValue(fieldName, out fieldInfo))
                        {
                            throw new InvalidOperationException(Strings.FormatMissingBackingField(entityType.Name, propertyName, fieldName));
                        }
                        if (!fieldInfo.FieldType.GetTypeInfo().IsAssignableFrom(property.PropertyType.GetTypeInfo()))
                        {
                            throw new InvalidOperationException(
                                      Strings.FormatBadBackingFieldType(fieldName, fieldInfo.FieldType.Name, entityType.Name, propertyName, property.PropertyType.Name));
                        }
                        memberInfo = fieldInfo;
                    }
                    else
                    {
                        memberInfo = _fieldMatcher.TryMatchFieldName(property, propertyInfo, fields);
                    }

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

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

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

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

            return(propertyMappings);
        }