0

Привет MVC и LINQ Эксперты,Перечня полевых названий как массив строк - 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 не является сложным типом.

Как передать функцию массив выражений с int и string?

ответ

1

Вы можете попробовать пропускание массива объектов (который является то, что ваше выражение ожидает) вместо того, чтобы пытаться использовать синтаксис массива инициализатора:

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

Это позволяет передавать произвольные типы объектов.

+0

Да! Так оно и было. Но мне пришлось исправить свой метод. См. Мой ответ для полного решения. –

0

Вы можете определить интерфейс IFieldName, который позволяет использовать его в вашем списке, а затем реализовать его в разных классах (int, error, string и т. Д.) Для фактических типов, которые происходят в вашей обработке.

Это примерно эквивалентно определению рва объекта, но восстанавливает безопасность типа.

0

С помощью Дарин Димитрия (идея пройти new 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 Validation:

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