2012-04-04 4 views
2

Ich habe diese Einheiten:Linq Abfrage mit geschweiften Klammern für anonyme Aktion/Funktion Körper

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

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

Dann habe ich allDependants Variable mit TypeOf List<AllDependant>, die einige Eltern und Kinder in Rechtsträger-Mix halten.

Später möchte ich von ihnen wählen und so etwas tun:

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 } 
      } 
     }); 

Notiere die spezifische Eigenschaft für Kind und Eltern mich verlangen die Eigenschaft auf ein neues Modell für die UI-Anzeige zu werfen und erhalten die ist nicht Anliegen der Entität. Ich kann die spezielle Eigenschaft nicht in die AllDependant-Basisklasse einfügen, da ich den Eigenschaftsnamen auf so viele Dateien umwandeln muss, einschließlich * .ascx, was mühsam ist. Aber es getan, indem Sie die Linq Select Erweiterung Methode oben, aber ich denke nur an diese:

Frage: Wie kann ich das gleiche in Linq Query?

Dieser Fehler auf dem select Schlüsselwort und den geschweiften Klammern geben:

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

Was denken Sie, indem es in Linq-Syntax gewinnen wird? – ChrisWue

+1

Der Fehler liegt daran, dass das Schlüsselwort 'new' fehlt. 'wähle neues {..}'. – alexn

+0

@ChrisWue, nicht ändern, nur zu denken, wie Funktionskörper in Linq Abfrage genau wie wir Funktionskörper in Lambda tun können. – CallMeLaNN

Antwort

3

Sie den bedingten Operator etwas wie und bekommen

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

Aber wie Sie sehen, dass ist kein großer verwenden würde Verbesserung. Es gibt keinen geeigneten Ort, um den Typ-Cast zu machen.

Die bessere Option scheint die Eigenschaften Name und SpecialInfo in eine Basisklasse (AllDependant oder eine spezielle Zwischenklasse) zu verschieben.

+0

+1 für den letzten Absatz. Beachten Sie, dass eine '' Sibling'' Klasse in '' allDependants' '' 'NullReferenceException'' ergibt -' 'InvalidCastException'' ist immer informativer, also würde ich einen Cast verwenden, –

+0

Danke, fast schon, aber Vielleicht möchte ich die Frage zu ändern, wie kann ich Linq-Abfrage mit Aktion/Funktion Körper anstelle von Ausdruck wie, wie wir in Lambda mit geschweiften Klammern tun können. – CallMeLaNN

+1

Sie können tun '(von d in ...). Wählen Sie (x => x)'. –

2

Eine Alternative wäre:

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); 

Der Nachteil dieses Ansatzes wäre, dass addDependants zweimal iteriert werden würde.

+0

Dies wird zweimal über '' allDependants' 'iterieren und die Typprüfung zweimal durchführen, aber andererseits ist es sicher, wenn '' allDependants' 'einen' 'AllDependant'' enthalten, der nicht' 'Parent'' oder' 'Child'' ist '(im Gegensatz zur OP-Lösung). –

+0

Ja, du hast Recht. Ich füge eine Notiz hinzu. – Phil

+0

Oh, ja, es ist nur eine Alternative zu meinem Beispiel, aber es ist nicht die Antwort :) Eigentlich möchte ich wissen, wie ich das gleiche mit Hilfe der Linq-Abfrage – CallMeLaNN

0

Eine weitere Möglichkeit der Reflexion mit

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

Während dies funktionieren könnte, ist es keine gute Sache zu tun: Leistung ist schlecht (im Vergleich zu dem ursprünglichen Ansatz) und Refaktorierung unfreundlich – ChrisWue

+0

@ChrisWue Reflection Leistung wird von der Implementierung abhängen. Wie p.GetType(). GetProperty ("Name") würde zwischengespeichert werden. Sie können eine solche Implementierung in vielen ORM-Frameworks finden. – shenhengbin

Verwandte Themen