예제 #1
0
        public EFEntityDescription()
        {
            Type entityType = typeof(TEntity);

            // Словарь: имя сущности - SQL идентификатор сущности извлеченные из контекста приложения.
            Dictionary <string, string> entitiesIds = typeof(ApplicationDbContext).GetProperties().Where(p =>
            {
                return(p.PropertyType.IsGenericType &&
                       p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet <>));
            }).ToDictionary(p => p.PropertyType.GenericTypeArguments.First().Name, p => GetEntityId(p.Name));

            // Получаем идентификатор SQL указанной сущности из словаря tableNames или атрибута Table.
            TableAttribute tableAttribute = entityType.GetCustomAttribute <TableAttribute>();

            EntityId = tableAttribute == null || string.IsNullOrWhiteSpace(tableAttribute.Name)
                ? entitiesIds[entityType.Name]
                : GetEntityId(tableAttribute.Name);

            // Массив вложенных и невложенных свойств текущей сущности.
            PropertyInfo[] allowedProperties = entityType.GetProperties().Where(p =>
            {
                return(!Attribute.IsDefined(p, typeof(NotMappedAttribute)) &&
                       p.GetMethod.IsPublic &&
                       !p.GetMethod.IsAbstract &&
                       !p.GetMethod.IsStatic);
            }).ToArray();

            // Список ключей: невложенное свойство - SQL идентификатор свойства текущей сущности.
            EntityProperties = allowedProperties.Where(p =>
            {
                return((p.PropertyType == typeof(string) || p.PropertyType.IsValueType) &&
                       !p.GetMethod.IsVirtual);
            })
                               .ToDictionary(p => p, p =>
            {
                var columnAttribute = p.GetCustomAttribute <ColumnAttribute>();
                string propertyName = columnAttribute == null || string.IsNullOrWhiteSpace(columnAttribute.Name)
                    ? p.Name
                    : columnAttribute.Name;

                return(GetPropertyId(EntityId, propertyName));
            });

            // Подключаемые сущности.
            Type[] joinedEntities = allowedProperties.Where(p =>
            {
                return(p.GetMethod.IsVirtual && entitiesIds.ContainsKey(p.PropertyType.Name) &&
                       p.PropertyType.IsClass &&
                       !typeof(IEnumerable).IsAssignableFrom(p.PropertyType) &&
                       p.PropertyType.GetProperties().Any(np =>
                {
                    return !Attribute.IsDefined(np, typeof(NotMappedAttribute)) &&
                    (np.PropertyType.IsValueType || np.PropertyType == typeof(string)) &&
                    np.GetMethod.IsPublic &&
                    !np.GetMethod.IsAbstract &&
                    !np.GetMethod.IsStatic;
                }));
            })
                                    .Select(p => p.PropertyType).ToArray();

            // Список ключей: вложенное свойство - SQL идентификатор свойства текущей сущности.
            var joinedEntitiesProperties = new List <KeyValuePair <PropertyInfo, string> >();

            foreach (Type joinedEntity in joinedEntities)
            {
                // Получаем идентификатор SQL подключаемой сущности из словаря tableNames или атрибута Table.
                TableAttribute joinedTableAttribute = joinedEntity.GetCustomAttribute <TableAttribute>();
                string         joinedEntityId       =
                    joinedTableAttribute == null || string.IsNullOrWhiteSpace(joinedTableAttribute.Name)
                        ? entitiesIds[joinedEntity.Name]
                        : GetEntityId(joinedTableAttribute.Name);

                // Список ключей: невложенное свойство - идентификатор SQL свойства подключаемой сущности.
                IEnumerable <KeyValuePair <PropertyInfo, string> > joinedEntityProperties = joinedEntity.GetProperties()
                                                                                            .Where(p =>
                {
                    return(!Attribute.IsDefined(p, typeof(NotMappedAttribute)) &&
                           p.GetMethod.IsPublic &&
                           (p.PropertyType == typeof(string) || p.PropertyType.IsValueType) &&
                           !p.GetMethod.IsAbstract &&
                           !p.GetMethod.IsStatic &&
                           !p.GetMethod.IsVirtual);
                })
                                                                                            .Select(p =>
                {
                    var columnAttribute = p.GetCustomAttribute <ColumnAttribute>();
                    var propertyName    = columnAttribute == null || string.IsNullOrWhiteSpace(columnAttribute.Name)
                        ? p.Name
                        : columnAttribute.Name;
                    propertyName = GetPropertyId(joinedEntityId, propertyName);

                    return(new KeyValuePair <PropertyInfo, string>(p, propertyName));
                });

                // Добавляем пары ключ - значение невложенных свойств подключаемой сущности
                // к вложенным свойствам указанной в параметре типе сущности.
                joinedEntitiesProperties.AddRange(joinedEntityProperties);
            }

            JoinedEntitiesProperties = joinedEntitiesProperties.ToDictionary(p => p.Key, p => p.Value);

            // Список кортежей описания подключаемой SQL сущности.
            JoinedEntitiesInfo = joinedEntities.Select(e =>
            {
                string PKey = JoinedEntitiesProperties[e.GetProperties().Single(p =>
                {
                    return(Attribute.IsDefined(p, typeof(KeyAttribute)) ||
                           p.Name.Contains($"{e.Name}id", StringComparison.OrdinalIgnoreCase));
                })];

                string FKey = EntityProperties.Single(p =>
                                                      p.Key.Name.Contains($"{e.Name}Id", StringComparison.OrdinalIgnoreCase)
                                                      ).Value;

                return(entitiesIds[e.Name], PKey, FKey);
            }).ToList();
        }