2012-04-04 1 views
2

У меня есть эти объекты:Linq запрос с фигурными скобками для анонимного тела действия/функций

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

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

Тогда я allDependants переменных с TYPEOF List<AllDependant>, который будет держать некоторые из детей и родители entitiy в смеси.

Позже, я хочу, чтобы выбрать один из них и сделать что-то вроде этого:

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

Примечания специфического свойства для детей и родителей требует от меня, чтобы бросить и получить собственность на новую модель для отображения пользовательского интерфейса, который не является предметом озабоченности. Я не могу поместить специальное свойство в базовый класс AllDependant, потому что мне нужно реорганизовать имя свойства на так много файлов, включая * .ascx, что является неприятным. Однако это было сделано с использованием метода расширения Linq Select выше, но я просто думаю об этом:

Вопрос: Как я могу сделать то же самое в Linq Query?

Это даст ошибку на select ключевого слова и фигурные скобки:

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

Что вы думаете, что вы получите, изменив его в синтаксис Linq? – ChrisWue

+1

Ошибка в том, что вам не хватает ключевого слова 'new'. 'select new {..}'. – alexn

+0

@ChrisWue, не меняя мышление, как делать тело функции в запросе Linq, как мы можем сделать тело функции в лямбда. – CallMeLaNN

ответ

3

Вы бы использовать условный оператор и получить что-то вроде

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

Но, как вы видите, что это не большая улучшение. Там нет удобного места для создания типа.

Лучший вариант, казалось бы, переместил свойства Name и SpecialInfo в базовый класс (AllDependant или специальный промежуточный класс).

+0

+1 для последнего абзаца. Обратите внимание, что класс '' Sibling'' в '' allDependants' приведет к '' NullReferenceException'' здесь. '' InvalidCastException'' всегда более информативен, поэтому я бы использовал листинг, –

+0

Спасибо, почти там, но Возможно, я хочу изменить вопрос: Как я могу создать запрос Linq с телом action/function вместо выражения так же, как, как мы можем сделать в Lambda, используя фигурные скобки. – CallMeLaNN

+1

Вы можете сделать '(from d in ...). Выбрать (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'' и дважды проверять тип проверки, но с другой стороны безопасно, если '' allDependants'' будет содержать '' AllDependant'''' '' Parent''' или '' Child'' '(в отличие от решения OP). –

+0

Да, вы правы. Я добавлю примечание. – Phil

+0

О, да, это просто альтернатива моему примеру, но это не ответ :) на самом деле я хочу знать, как я могу сделать то же самое, используя запрос Linq – CallMeLaNN

0

Другой способ использования Reflection

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 («Имя») будет кэшироваться. Вы можете найти такую ​​реализацию во многих инфраструктурах ORM. – shenhengbin

Смежные вопросы