2013-03-08 2 views
0

У меня возникли проблемы с плохо именованных свойств:C# фильтрации имен динамических свойств в лямбда

public class Word 
{ 
    public string Alt01 { get;set; } 
    public string Alt02 { get;set; } 
    public string Alt03 { get;set; } 
    public string Alt04 { get;set; } 
    public string Alt05 { get;set; } 
} 

Это, вероятно, было одно свойство типа List<string>. Но кто-то другой придумал эту идею, и я не могу изменить структуру на данный момент.

У меня есть метод, который возвращает много объектов Word. То, что я хотел бы сделать, - отфильтровать каждый экземпляр Word, который имеет соответствующую строку в одном или нескольких свойствах AltXX.

Это то, что я до сих пор:

foreach(var word in resultList) //<-- List<Word> 
{ 
    var alt01 = word.GetType().GetProperty("alt01").GetValue(word, null); 
} 

Это будет работать, как мой фильтр, если я продлить его немного. Но мой вопрос: разрешимо ли это с помощью лямбда-выражений?

+0

он ограничивается Alt05 или выходит даже за что? – publicgk

+0

@publicgk До 15 – Johan

+0

количество записей Alt ## может варьироваться в зависимости от слова? И это свойства? Как, черт возьми, вы получили список разнородных объектов? – Nevyn

ответ

7

Таким образом, мы начнем с простого помощника (возможно расширение) метод, так как у нас есть куча свойств, а не список:

public static IEnumerable<string> getAlts(Word word) 
{ 
    yield return word.Alt01; 
    yield return word.Alt02; 
    yield return word.Alt03; 
    yield return word.Alt04; 
    yield return word.Alt05; 
} 

Вы можете рефакторинг, что использовать отражение, если это может иметь N свойства а не ровно пять. Бог поможет вам, если это действительно так. Удалите разработчика, который поместил вас в эту позицию, вместо того, чтобы просто использовать для меня один раз List.

При том, что это не так уж плохо:

List<Word> words = new List<Word>(); 

string searchText = "foo"; 
var query = words.Where(word => getAlts(word).Any(alt => alt.Contains(searchText))); 

Я хочу, чтобы слова WhereAny из альта для этого слов содержат искомый текст. Он читается точно так же, как работает.

+0

Возможно, он просто добавит его в класс как метод.Как 'IEnumerable GetAlts() {/ ** Код ** /}' – Romoku

+0

@Romoku Потенциально. Хотелось бы подумать, что если он будет контролировать определение класса, он может просто реорганизовать его, чтобы использовать «Список», но я полагаю, что это может быть слишком большой работой. Если он может поместить его в класс, он, безусловно, принадлежит. – Servy

+0

@Servy, у вашей шлепки теперь есть кандидат. OP подтвердил, что это до Alt15. :) – publicgk

0

Лучшее, что вы можете сделать, это использовать отражение один раз в начале вашего приложения, чтобы построить деревья выражений, которые компилируются в лямбда, а затем сохранить эти лямбды для повторного использования.

Цена за медленность отражения выплачивается только один раз, а затем она так же быстро, как если бы вы скомпилировали ее с самого начала.

Однако, это боль в шее, чтобы написать эти деревья выражений, поэтому, если вас не беспокоит производительность (она медленная, но не THAT медленная), тогда ваше отражение должно быть прекрасным.

1

Вы можете преобразовать класс в List<string> обратным образом, создав вспомогательный класс.

E.G.

class QueryFriendlyWordList 
{ 
    public List<string> Words; 

    public QueryFriendlyWordList(Word words) 
    { 
      Words = new List<string> {words.P1,words.P2, words.P3, words.P4}; 
    } 
} 

Использование

 Word words = new Word {P1 = "abcd", P2 = "abc", P3 = "def", P4 = "qwre"}; 
     var queryable = new QueryFriendlyWordList(words); 
     var result = queryable.Words.Where(w => w.Contains("a")); 

Static еще проще:

static class WordConverter 
{  
    public static List<string> Convert(Word words) 
    { 
      return new List<string> {words.P1,words.P2, words.P3, words.P4}; 
    } 
} 
+0

Спасибо, выглядит чисто и просто :) – Johan

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