c#在lambda中过滤动态属性名
本文关键字:动态 属性 过滤 lambda | 更新日期: 2023-09-27 18:02:57
我遇到了命名不当的属性:
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
对象。我想做的是过滤掉在一个或多个AltXX
属性中具有匹配字符串的每个Word
实例。
这是我目前为止写的:
foreach(var word in resultList) //<-- List<Word>
{
var alt01 = word.GetType().GetProperty("alt01").GetValue(word, null);
}
如果我稍微扩展一下,它就可以作为我的过滤器。但我的问题是:这是可解决使用lambda表达式吗?
所以我们将从一个简单的助手(可能是扩展)方法开始,因为我们有一堆属性,而不是一个列表:
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个属性而不是5个,你可以重构它来使用反射。上帝保佑你,如果你真的是这样的话。打那些让你陷入这种境地的开发者,而不是对我来说只使用一次List
。
有了这个,还不算太糟:
List<Word> words = new List<Word>();
string searchText = "foo";
var query = words.Where(word => getAlts(word).Any(alt => alt.Contains(searchText)));
我希望该词的alt的Where
Any
包含搜索文本。
您可以通过创建辅助类以向后兼容的方式将类转换为List<string>
。
如
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 class WordConverter
{
public static List<string> Convert(Word words)
{
return new List<string> {words.P1,words.P2, words.P3, words.P4};
}
}
你最好在应用程序开始时使用反射来构建表达式树,这些表达式树被编译成lambdas,然后保存这些lambdas以便重用。
反射速度慢的代价只付出一次,然后它就像你从头编译一样快。
然而,编写这些表达式树是一件令人痛苦的事情,所以如果你不关心性能(它很慢,但不是那么慢),那么你的反射应该没问题。