protected List <MappedProperty> GetPropertiesHierarchy(Type rootType, Type propertyType, List <string> parentPropertyNames) { List <MappedProperty> list = new List <MappedProperty>(); BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; PropertyInfo[] allEntityProperties = propertyType.GetProperties(bindingFlags); List <PropertyInfo> mappedProperties = allEntityProperties.Where( p => { Type underlined = Nullable.GetUnderlyingType(p.PropertyType); Type property = underlined ?? p.PropertyType; return(property.IsValueType == true || property.IsPrimitive || property == typeof(string)); }) .ToList(); foreach (PropertyInfo supportedProp in mappedProperties) { List <string> namesHierarchy = parentPropertyNames.ToList(); namesHierarchy.Add(supportedProp.Name); string efDefaultName = ReflectionUtility.ConcatenateEfPropertyName(namesHierarchy); string efMappedName = DbContextExtensions.GetColumnName(_context, rootType, efDefaultName); list.Add(new MappedProperty { PropertyInfo = supportedProp, EfDefaultName = efDefaultName, EfMappedName = efMappedName }); } List <PropertyInfo> complexProperties = allEntityProperties.Where( p => p.PropertyType != typeof(string) && p.PropertyType.IsClass) .ToList(); //Exclude navigation properties //ICollection properties are excluded already as interfaces and not classes. //Here we exclude virtual properties that are not ICollection, by checking if they are virtual. complexProperties = complexProperties .Where(x => x.GetAccessors()[0].IsVirtual == false) .ToList(); foreach (PropertyInfo complexProp in complexProperties) { List <string> namesHierarchy = parentPropertyNames.ToList(); namesHierarchy.Add(complexProp.Name); List <MappedProperty> childProperties = GetPropertiesHierarchy(rootType, complexProp.PropertyType, namesHierarchy); if (childProperties.Count > 0) { list.Add(new MappedProperty { PropertyInfo = complexProp, ChildProperties = childProperties }); } } return(list); }