0

您好 MVC 和 LINQ 专家,

我有一个看起来像这样的模型:

 public class SomeClass : IValidatableObject
 {
    public string SomeString { get; set; }
    public string SomeString2 { get; set; }
    public int SomeInteger { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
       //... IF there is some error...THEN
       yield return new ValidationResult("Some Error Message.", GetFieldNames(() => new []{ this.SomeString }));
    }

 }

如您所见,我正在调用 GetFieldNames,它接受一个表达式,并将表达式成员作为字符串数组返回给您。根据我最近阅读的一本书,将错误链接到字段的方法是将其作为字符串传递,如下所示:

  yield return new ValidationResult("Some Error Message.", new []{ "SomeString" }));

但我想成为强类型,所以这是我写的方法:

  public static string[] GetFieldNames(Expression<Func<object[]>> exp)
    {
        //Build a string that will in the end look like this: field1,field2,field3
        //Then we split(',') it into an array and return that string array. 
        string fieldnames = "";

        MemberExpression body = exp.Body as MemberExpression;

        if (body == null)
        {   
            NewArrayExpression ubody = (NewArrayExpression)exp.Body;
            foreach(MemberExpression exp2 in ubody.Expressions)
            {
                fieldnames += exp2.Member.Name + ",";
            }
            fieldnames = fieldnames.TrimEnd(',');

        }
        if(fieldnames.Length > 0)
            return fieldnames.Split(',');
        else
            return new string[]{};
    }

当前使用情况:

GetFieldNames(() => new[] { this.SomeString , this.SomeString2 });

输出:

{ "SomeString" , "SomeString2" }

这工作正常。

问题是,如果我按如下方式使用它,它会给我一个错误(编译时):

GetFieldNames(() => new[] { this.SomeString , this.SomeInteger });

错误: No best type found for implicitly-typed array

我想要的输出:

{ "SomeString" , "SomeInteger" }

我不能传入对象数组,因为 int 不是复杂类型。

如何使用intand向函数传递表达式数组string

4

3 回答 3

1

您可以尝试传递一个对象数组(这是您的表达式所期望的),而不是尝试使用数组初始值设定项语法:

GetFieldNames(() => new object[] { this.SomeString, this.SomeInteger });

这允许您传递任意对象类型。

于 2013-03-12T21:57:07.090 回答
0

在 Darin Dimitri 的帮助下(传递 anew object[]而不是new [] 以下代码的想法将确保您IValidatableObject现在可以进行强类型化,而不仅仅是一个字符串数组。

    public static string[] GetFieldNames(Expression<Func<object[]>> exp)
    {
        string fieldnames = "";

        MemberExpression body = exp.Body as MemberExpression;

        if (body == null)
        {
            NewArrayExpression ubody = (NewArrayExpression)exp.Body;
            foreach (Expression exp2 in ubody.Expressions)
            {
                if (exp2 is MemberExpression) {
                    fieldnames += ((MemberExpression)exp2).Member.Name + ",";
                }
                else {
                    var op = ((UnaryExpression)exp2).Operand;
                    fieldnames += ((MemberExpression)op).Member.Name + ",";
                } 
            }
            fieldnames = fieldnames.TrimEnd(',');

        }

        if(fieldnames.Length > 0)
            return fieldnames.Split(',');
        else
            return new string[]{};
    }

用法:

GetFieldNames(() => new object[] { this.SomeString, this.SomeInteger }));

MVC 验证的用法:

yield return new ValidationResult("Some Error.", GetFieldNames(() => new object[] { this.SomeString, this.SomeInteger }));

于 2013-03-13T21:17:43.320 回答
0

您可以定义一个接口 IFieldName 以在您的列表中使用,然后在不同的类(int、error、string 等)中为您处理中出现的实际类型实现它。

这大致相当于定义一个对象数组,但恢复了类型安全。

于 2013-03-12T22:02:46.143 回答