2012-04-04 11 views
2

私は、このエンティティを持っている:LINQクエリ

public class Parent: AllDependant 
{ 
    /*Properties goes here*/ 
} 

public class Children: AllDependant 
{ 
    /*Properties goes here*/ 
} 

それから私は、ミックスの中で両親と子供entitiyの一部を維持しますtypeofをList<AllDependant>allDependants変数を持っています。

その後、私は彼らから選択して、このような何かやりたい:

var selectedDependantInfos = allDependants 
     .Select(dependant => 
     { 
      if (dependant is Parent) 
      { 
       var parent = dependant as Parent; 
       return new { Name = parent.Name, SomeSpecialInfo = parent.ParentInfo }; 
      } 
      else 
      { 
       var child = dependant as Children; 
       return new { Name = child.Name, SomeSpecialInfo = child.ChildInfo } 
      } 
     }); 

注子と親のための特定のプロパティは、キャストやUIの表示のための新しいモデルにプロパティを取得するために私を必要としていますエンティティの関心事ではありません。 * .ascxを含む非常に多くのファイルでプロパティ名をリファクタリングする必要があるため、AllDependantベースクラスに特別なプロパティを入れることができません。これは面倒です。しかし、上記のLinq Select拡張メソッドを使用して完了しましたが、私はちょうどこれを考えています:

質問:Linqクエリで同じことをどうやって行えますか?あなたは条件演算子を使用して

from dependant in allDependants    
    select dependant is Parent 
     ? new { Name = (dependant as Parent).Name, /* Parent fields */ } 
     : new { Name = (dependant as Children).Name, /* Child fields */ } 

のようなものになるだろう

var selectedDependantInfos = from dependant in allDependants 
          select 
          { 
           /* the same if statement goes here */ 
          } 
+1

を使用する別の方法は何あなたはLINQの構文にそれを変更することで獲得すると思いますか? – ChrisWue

+1

エラーは 'new'キーワードがないためです。 '新しい{..}を選択します。 – alexn

+0

@ChrisWue、ちょうど私たちがLambdaで関数体を行うことができるように、Linqクエリで関数本体を行う方法を考え直すことはありません。 – CallMeLaNN

答えて

3

をしかし、あなたはそれは素晴らしいではありません見るように:

これはselectキーワードと中括弧でエラーになります改善。タイプキャストを行う便利な場所はありません。

より良いオプションは、NameクラスとSpecialInfoプロパティを基本クラス(AllDependantまたは特別な中間クラス)に移動するように見えます。

+0

+1最後の段落。 '' AllDependants''の '' Sibling''クラスは '' NullReferenceException''を返します - '' InvalidCastException''はもっと有益な情報なので、キャストを使用します。 –

+0

ありがとうございます。多分私はラムダ内で中括弧を使用してどのように行うことができるかのように、式の代わりにアクション/関数本体でLinqクエリを作成する方法を質問に変更したいと思うかもしれません。 – CallMeLaNN

+1

'(from d in ...)。Select(x => x)'を実行できます。 –

2

選択肢は次のようになります。

var parents = allDependants.OfType<Parent>.Select(p => new { Name = p.Name, .... }; 
var children = allDependants.OfType<Children>.Select(c => new { Name = c.Name, .... }; 

var combined = parents.Concat(children); 

このアプローチの欠点をaddDependantsが二回以上反復されることになります。

+0

これは '' allDependants''を2回繰り返し、型チェックを2回実行しますが、 '' AllDependants''に '' Parent''や '' Child''以外の '' AllDependant''が含まれていれば安全です。 (OPソリューションとは対照的に) –

+0

はい、あなたは正しいです。私はメモを追加します。 – Phil

+0

ああ、まあ、私の例の代わりに、それは答えではありません:実際に私はLinqクエリを使用して同じことを行うことができる方法を知ってほしい – CallMeLaNN

0

反射

var selectedDependantInfos = from p in allDependants 
         let key = p is Parent ? "ParentInfo" : "ChildInfo" 
         select new { 
          Name = p.GetType().GetProperty("Name").GetValue(p, null).ToString(), 
          SomeSpecialInfo = p.GetType().GetProperty(key).GetValue(p, null).ToString() 
         }; 
+0

これはうまくいくかもしれませんが、パフォーマンスが悪く(元のアプローチと比較して)悪いです。 – ChrisWue

+0

@ChrisWueリフレクションのパフォーマンスは実装によって異なります。 p.GetType()と同様にGetProperty( "Name")がキャッシュされます。多くのORMフレームワークでそのような実装を見つけることができます。 – shenhengbin