2012-02-23 15 views
1

こんにちは最愛のコミュニティ:DSystem.NullReferenceException選択句で

今私は私の最初の大きなプロジェクトに取り組んでおり、ちょっと立ち往生しています。 入力を検証しようとしています。

var header = from name in v.Validate(it => it.Name).Required().MaxLength(Constants.String.NameLength) 
        from startDate in v.Validate(it => it.StartDate).Required().After(DateTime.Today) 
        from endDate in v.Validate(it => it.EndDate).Required().After(DateTime.Today) 
        from endTime in v.Validate(it => it.EndTime).BlockErrors().Required().ReplaceIfInvalid(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 30, 0)) 
        from requestedCurrency in v.Validate(it => it.RequestedCurrency).Required() 
        from language1 in v.Validate(it => it.Language1).Required() 
        from language2 in v.Validate(it => it.Language2) 
        from language3 in v.Validate(it => it.Language3) 
        from hasMoreInformation in v.Validate(it => it.HasMoreInformation) 
        // TODOJP: If "hasMoreInformation" is true, then "moreInformationEmail" has to be required. 
        from moreInformationEmail in v.Validate(it => it.MoreInformationEmail).IsEmail()//.RequiredOr(p => !hasMoreInformation) 
        from isAnonymous in v.Validate(it => it.IsAnonymous) 
        select new AnnouncementHeader(
         currentUser, 
         type, 
         name, 
         startDate, 
         endDate.SetTime(new Time(endTime.Hour, endTime.Minute)), 
         isAnonymous, 
         infoField, 
         requestedCurrency, 
         language1, 
         language2, 
         language3, 
         hasMoreInformation, 
         moreInformationEmail); 
: "RequiredOr" 機能を呼び出すために

public Validatable<TProperty> Validate<TProperty>(
     Expression<Func<TEntity, TProperty>> expr) 
    { 
     return new Validatable<TProperty>(
      new ErrorTrackerWrapper(ErrorTracker, expr.Body), expr.Compile()(Value)); 
    } 

この部分:私はこれを使用している通常の検証のために

public static Validatable<string> RequiredOr(this Validatable<string> that, Func<Validatable<string>, bool> func) 
{ 
    return that.DoEvaluate && !(func(that) || that.Value != null) 
      ? that.Error(ML.Get("Validation", "IsRequired")) 
      : that; 
} 

:したがって

私はこの機能を使用しています

これまでのところ正しいですが、「RequiredOr」部分の「hasMoreInformation」はどういう意味か教えてくれますNullReferenceException

エラーを "RequiredOr"機能までトレースすることができました。

"HasMoreInformation"が真であるかどうかを確認して、フィールドを "必須"に設定するかどうかを確認したいと思います。

私はあなたに何を伝えようとしているのか理解してくれることを願っています。 ご協力いただきありがとうございます。

+0

Validate()のコードを投稿し、linqクエリ全体を投稿してください。どんなことが起こっているのかを推測するのは難しいです。タイトルにはselect句に問題があると書かれていますが、select句は含まれていません。 – phoog

+0

コードを更新しました。 エラーはselect句にはありません。残念ですが、moreInformationEmailの "RequiredOr"部分にあります。 (コメント部分を見て) – KampfFussel

+0

申し訳ありませんが、私はまだ混乱しています。 'Validate()'はIEnumerableを返しますか?それとも、クエリの理解構文に従う他の型を返しますか? – phoog

答えて

0

潜在的にnullのオブジェクトでは、フィールドが存在するかどうかをテストする前に、それが真であるかどうかをテストする必要があります。ルールを破棄した結果、null ref例外が発生します。それがどのように機能するかです。

アイテムがNULL可能である場合、常にnullになる可能性があります。値をデフォルトにするとそうしないようにすることができますが、デフォルトは単一の意味を持たなければならず、「デフォルトにする」と「ユーザーが明示的に設定できる」の両方を意味するわけではありません。

デフォルト値が意味をなさない場合は、検証前にnullオブジェクトが有効かどうかを示します。

私は文脈が非常に小さいので、問題を解決するためにこれを長い形で書くことをお勧めします。その後、遅延実行スタイル(LINQ)で再考することができます。これは、項目がnullではない場合や、明示的に指定されていない他の項目(後に必要なチェックについてのコメントに基づいて)のみを選択したいと思うためです。あなたがLINQする前に問題を歩いてください。

NEW:解決策をLINQする前に最後の行に固執しています(LINQだけでなく、ここにすべての遅延実行を含めます)。

私は実際にはステートメントに多くの時間を費やすことなく、いくつかのLINQといくつかの拡張メソッド(連鎖メソッドを持つ流体構文、blah、blah)を持っています。これらはすべて遅延実行です。シンボルをプルダウンしてスタックをポップすると、遅延実行の順序が問題の一部になることがあります。それはしばしば、抽象化のスチームパイルをデバッグする唯一の方法です。 (はい、関数ポインタと拡張メソッドを含む47行のネストされたLINQステートメントを見たことがあります)

流体プログラミングスタイルを使用する場合、基本的に擬似IoCタイプのパターンが実行されます。あなたが左にいっぱいになるまで、次の方法に進む。非常に悪い類推のような説明なので、私はおそらく訂正されるでしょうが、正しい方法でフローを保つために関数ポインタを使って作業しています。例:

Colonel.Sanders.Loves.Chicken( "fried");

関数ポインタ、拡張メソッド、RX、ああ私!哲学の観点からはかなり素敵なものですが、これがどういう仕組みを本当に理解していなければ悪いジュジュになりがちです。それはしばしば非常に明確な構文を作りますが、デバッグの悪夢を作ります。

食事プランやファーストフードのレストランを選択するためにLINQステートメントをさらに守ると、さまざまな方向から多くの延期されたグーグーが出ることになります。また、1つのビットが正しい順序でない場合、必要な先行の前にいくつかのコードが実行されます。 LINQと拡張メソッドは異なるメソドロジを使用するため、それらを混在させると、ビットが誤った順序で実行される可能性が高くなります。また、シンボルを使用したデバッグは、実行時に遅延抽象の全体が「コンパイル」されるため、ハックする唯一の方法です。

この長いポストを終了するには、デバッグスルーして、なぜヌルrefを取得しているのかを把握する必要があります(おそらく遅延実行のスタックで呼び出しが誤っている可能性があります)。またはb)まず非繰延方式を使用します(または、一度に1つのビットを実行していますか?)。

+0

アイテムはヌル可能ではありません。これは真または偽で、デフォルトは偽です – KampfFussel

+0

セットの検証とデータの単一コールの両方を達成しようとしています。さらに、拡張メソッドを積み重ねたLINQ構造体を連鎖させて、実行を延期するさまざまな手段を使用しています。 –

+0

ありがとうございます。私はそれが私が必要としていたものだと思う。 私の投稿に書いた(編集した)ように、私は 'RequireOr()'関数にデバッグすることができ、それが 'func(that)'の問題であることに気付きました。 – KampfFussel

関連する問題