Как исключить свойства Enum с общими текучими отображениями EF4 / CTP5? - PullRequest
1 голос
/ 13 марта 2011

Я просто погружаюсь в использование первого кода с CTP5 для Entity Framework. Чтобы облегчить задачу настройки отображений базы данных, я создал себе небольшой вспомогательный класс, который будет служить базовым классом для любых пользовательских сопоставлений, но я не могу понять, как заставить работать последний оператор в методе.

Я нахожу все открытые свойства типа Enum и затем вызываю метод .Ignore для каждого свойства, найденного в данном типе. Код использует Fasterflect для отражения и небольшой помощник ForEach, но должно быть достаточно очевидно, что делает код.

internal abstract class AbstractMappingProvider<T> : IMappingProvider where T : class
{
    public EntityTypeConfiguration<T> Map { get; private set; }

    public virtual void DefineModel( ModelBuilder modelBuilder )
    {
        Map = modelBuilder.Entity<T>();

        Map.ToTable( typeof(T).Name );

        typeof(T).Properties( Flags.Public | Flags.Instance )
            .Where( p => p.PropertyType.IsEnum )
            .ForEach( p => Map.Ignore( e => p ) );
    }
}

Выполнение вышеизложенного дает мне следующую ошибку:

System.InvalidOperationException: 
The expression 'e => value(Domain.AbstractMappingProvider`1+<>c__DisplayClass3[Domain.User]).p' is not a valid property expression.
It must be of the form 'e => e.Property'.

Как я могу использовать "p" (который на самом деле является свойством "e"), чтобы это не только компилировалось, но и работало? : о)

Я надеюсь, что у кого-то есть хитрый трюк, чтобы решить это. Альтернативные решения приветствуются, но помните, что вся идея состоит в том, чтобы не вызывать Map.Ignore для каждого свойства перечисления.

Ответы [ 2 ]

1 голос
/ 18 марта 2011

При этом используются стандартные библиотеки отражений .NET, но я уверен, что вы можете преобразовать его в более быстрый, если хотите. Я добавил метод Ignore в AbstractMappingProvider, чтобы мы могли использовать MakeGenericMethod (), чтобы разрешить универсальный тип для свойства во время выполнения, чтобы привести приведенную к этому моменту лямбду к правильному типу выражения. Там может быть лучший / быстрее / проще способ сделать это.

В качестве примечания, я вполне уверен, что в коде, который является первым Release Candidate (частью кандидата на выпуск Entity Framework 4.1), перечисления уже игнорируются по умолчанию при отображении по соглашению.

internal abstract class AbstractMappingProvider<T> : IMappingProvider where T : class
{
    public EntityTypeConfiguration<T> Map { get; private set; }

    public virtual void DefineModel(DbModelBuilder modelBuilder)
    {
        Map = modelBuilder.Entity<T>();

        Map.ToTable(typeof(T).Name);

        var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.PropertyType.IsEnum);

        var parameterExpression = Expression.Parameter(typeof(T), "e");

        foreach (var propertyInfo in properties)
        {
            // Build up the expression
            var propertyExpression = Expression.Property(parameterExpression, propertyInfo);
            var funcType = typeof (Func<,>).MakeGenericType(typeof (T), propertyInfo.PropertyType);
            var ignoreExpression = Expression.Lambda(funcType, propertyExpression, new[] {parameterExpression});

            // Call the generic Ignore method on this class, passing in the expression
            var ignoreMethod = this.GetType().GetMethod("Ignore");
            var genericIgnoreMethod = ignoreMethod.MakeGenericMethod(propertyInfo.PropertyType);
            genericIgnoreMethod.Invoke(this, new object[]{ignoreExpression});
        }
    }

    public void Ignore<TPropertyType>(LambdaExpression lambdaExpression)
    {
        var expression = (Expression<Func<T, TPropertyType>>) lambdaExpression;
        Map.Ignore(expression);
    }
}
1 голос
/ 13 марта 2011

Проблема в том, что P является объектом PropertyInfo. Этот класс имеет метаданные о свойстве, но ничего не знает о значениях, присвоенных свойству различным объектам. Вам придется вручную создать объект Expression для передачи в метод Ignore на основе использования имени свойства, которое вы можете получить из P.

...