简体   繁体   English

C#在lambda中过滤动态属性名称

[英]c# filtering dynamic property names in lambda

I'm having trouble with poorly named properties: 我遇到名称不正确的属性的麻烦:

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

This should probably have been one property of the type List<string> . 这可能应该是List<string>类型的一个属性。 But someone else came up with this idea, and I can't change the structure at the moment. 但是其他人想出了这个主意,目前我无法更改结构。

I have a method that returns a lot of Word objects. 我有一个返回很多Word对象的方法。 What I would like to do is to filter out each Word instance that has a matching string in one or more of the AltXX properties. 我想做的是过滤掉一个或多个AltXX属性中具有匹配字符串的每个Word实例。

This is what I have so far: 这是我到目前为止的内容:

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

This would work as my filter if I extend it a bit. 如果我稍微扩展一下,它将作为我的过滤器。 But my question is: Is this solvable using lambda expressions? 但是我的问题是:使用lambda表达式可解决吗?

So we'll start with a simple helper (possibly extension) method since we have a bunch of properties and not a list: 因此,我们将从一个简单的辅助方法(可能是扩展方法)开始,因为我们有很多属性而不是列表:

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

You could refactor that to use reflection if it could have N properties instead of exactly five. 如果可以具有N个属性而不是五个属性,则可以将其重构为使用反射。 God help you if that's really the case for you. 如果确实如此,那么上帝会帮助您。 Slap the developer who put you in that position instead of just using a List once for me too. 打招呼让您处于该位置的开发人员,而不仅仅是对我使用一次List

With that, it's not too bad: 这样,还算不错:

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

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

I want the words Where Any of the alt's for that word contain the search text. 我想要单词“ Where Any一个alt都包含搜索文本”。 It reads just like it works. 它读起来就像它在工作一样。

You can convert the class to List<string> in a backwards compatible way by creating a helper class. 您可以通过创建助手类以向后兼容的方式将类转换为List<string>

EG 例如

class QueryFriendlyWordList
{
    public List<string> Words;

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

Usage 用法

        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 is even easier: 静态甚至更容易:

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

Best you can do is use reflection one time at the start of your app to build expression trees, which compile into lambdas, then save those lambdas to be re-used. 最好的办法是在应用程序启动时使用反射一次来构建表达式树,将其编译为lambda,然后保存这些lambda以供重新使用。

The price for the slowness of reflection is only paid once, then afterward it's as fast as if you had compiled it from the beginning. 反射缓慢的代价仅需支付一次,然后此价格就如同您从一开始就对其进行编译一样快。

However, it's a pain in the neck to write those expression trees, so if you're not concerned about performance (it's slow, but not THAT slow), then your reflection should be fine. 但是,编写这些表达式树很麻烦,因此,如果您不关心性能(速度很慢,但不那么慢),那么您的反射应该很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM