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の助けを借りて( 次のコードの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検証の使用法:

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 に答える