【问题标题】:ValidationAttribute ReduxValidationAttribute Redux
【发布时间】:2009-05-29 16:21:52
【问题描述】:

参考:Creating a ValidationAttribute to ensure unique column values.

好的...让我们尝试重新构建问题:

来自here我已经撕掉了这段代码:

    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);

正如我所说的 here 没有帮助的答案。

  • var enumerator = ((IEnumerable)table).GetEnumerator();object code = enumerator.MoveNext() ? enumerator.Value : null;
    在我尝试构建表达式树时没有用。
  • IEnumerable<object> tableGeneric = ((IEnumerable)table).OfType<object>();
    我尝试时遇到问题:
    object code = tableGeneric.FirstOrDefault(predicate);

所以,我被困住了。有什么想法吗?

谢谢。

【问题讨论】:

    标签: c# linq-to-sql validation lambda


    【解决方案1】:

    您可能正在寻找的最终结果是,据我所知,您确实想要这样的方法:

    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() 的委托,这样您就不必多次对给定类型使用慢反射来执行类型绑定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-11
      • 2012-09-21
      • 2016-04-18
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 2016-12-23
      相关资源
      最近更新 更多