ValidationAttribute Redux - PullRequest
       11

ValidationAttribute Redux

0 голосов
/ 14 мая 2009

Ссылка на: Создание атрибута ValidationAttribute для обеспечения уникальных значений столбца.

Хорошо ... Давайте попробуем перефразировать вопрос:

с здесь Я скопировал этот код:

    static TEntity Get<TEntity, TKey>(this DataContext ctx, TKey key) where TEntity : class
    {
        var table = ctx.GetTable<TEntity>();
        var pkProp = (from member in ctx.Mapping.GetMetaType(typeof(TEntity)).DataMembers
                      where member.IsPrimaryKey
                      select member.Member).Single();
        ParameterExpression param = Expression.Parameter(typeof(TEntity), "x");
        MemberExpression memberExp;
        switch (pkProp.MemberType)
        {
            case MemberTypes.Field: memberExp = Expression.Field(param, (FieldInfo)pkProp); break;
            case MemberTypes.Property: memberExp = Expression.Property(param, (PropertyInfo)pkProp); break;
            default: throw new NotSupportedException("Invalid primary key member: " + pkProp.Name);
        }
        Expression body = Expression.Equal(
        memberExp, Expression.Constant(key, typeof(TKey)));
        var predicate = Expression.Lambda<Func<TEntity, bool>>(body, param);
        return table.Single(predicate);
    }

Это метод расширения DataContext, в котором есть вещи, которые мне нужны. Тем не менее, для этого требуются общие параметры, которых у меня нет в наличии - атрибуты не допускают общих подкасс, так что ...

Я взломал код до этого момента:

    public override bool IsValid(object value)
        SomeDataContext context = SomeDataContext.GetNewDataContext();
        var table = context.GetTable(_EntityType);
        var codeProp = (from member in context.Mapping.GetMetaType(_EntityType).DataMembers
                        where member.Name == _PropertyName
                        select member.Member).Single();
        ParameterExpression param = Expression.Parameter(_EntityType, "x");
        MemberExpression memberExp = Expression.Property(param, (PropertyInfo)codeProp); 
        Expression body = Expression.Equal(memberExp, Expression.Constant(value, typeof(char)));
        Type lambdaType = typeof(Func<,>).MakeGenericType(_EntityType, typeof(bool)); 
        var predicate = Expression.Lambda(lambdaType, body, param); 
        object code = table.FirstOrDefault(predicate);
        if (code != null)
        {
            return false;
        }
        return true;
    }

Эта строка плохая:

        object code = table.FirstOrDefault(predicate);

как я сказал здесь ответы на которые не помогают.

  • var enumerator = ((IEnumerable)table).GetEnumerator();object code = enumerator.MoveNext() ? enumerator.Value : null;
    бесполезен в моей попытке построить дерево выражений.
  • IEnumerable<object> tableGeneric = ((IEnumerable)table).OfType<object>();
    возникают проблемы при попытке:
    object code = tableGeneric.FirstOrDefault(predicate);

Итак, я застрял. Есть идеи?

Спасибо.

1 Ответ

0 голосов
/ 29 мая 2009

В конечном итоге вы, возможно, ищете, что, насколько я могу судить, вам нужен такой метод, как:

public bool IsValid<TEntity>()
{
    // validation logic goes here
}

Чтобы вы могли выполнять необходимые проверки, но вам необходимо реализовать их в методе, который имеет только доступный тип времени выполнения:

public bool IsValid(Type entityType)
{
    // ???
}

Если это так, то вы реализуете первый блок кода с нужной вам логикой и реализуете второй метод как:

public bool IsValidWrapper(Type entityType)
{
    // You may want to be stricter than this, but the essence is to
    // get a handle to the generic method first...
    MethodInfo genMethod = GetType().GetMethod("IsValid");

    // Bind it to the type you want to operate on...
    MethodInfo method = genMethod.MakeGenericMethod(entityType);

    // And invoke it...
    return (bool) method.Invoke(this, null);
}

Он не выиграет конкурсы красоты или спектакли, но даст вам то, что вам нужно. И обратите внимание, что, если производительность является проблемой, вы можете оставить поиск от Type до делегата с подписью bool delegate(), чтобы вам не приходилось использовать медленное отражение для данного типа более одного раза для выполнения привязки типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...