【问题标题】:Building a C# Linq helper构建 C# Linq 助手
【发布时间】:2010-08-16 12:29:32
【问题描述】:

我正在尝试使用 Linq 构建一个实用方法,以帮助我进行常见的 Linq-to-Objects 搜索。

我有一个 PropertyTbl 对象,它引用了一个地址。 我有一个IEnumerable<PropertyTbl>。 我写了一个助手,它接受一个IEnumerable<Address>,一些搜索条件返回一个IEnumerable<Address>,它在迭代时会给我匹配的地址。

但是我不知道如何将两者连接在一起,因为虽然我可以在我的 IEnumerable<PropertyTbl> 上执行 .Select() 以获得可枚举的地址,但我需要结果为 IEnumerable<PropertyTbl>

这是我的帮助代码

    public static IEnumerable<Address> BuildAddressWhereClause(IEnumerable<Address> addresses, string value, AddressSearchOptions options)
    {
        string search = value.ToUpper();

        if ((options & AddressSearchOptions.Address1To4) == AddressSearchOptions.Address1To4)
        {
            addresses = addresses.Where(o => o.Address1.ToUpper().Contains(search)
                                             || o.Address2.ToUpper().Contains(search)
                                             || o.Address3.ToUpper().Contains(search)
                                             || o.Address4.ToUpper().Contains(search));
        }

        if ((options & AddressSearchOptions.City) == AddressSearchOptions.City)
        {
            addresses = addresses.Where(o => o.City.ToUpper().Contains(search));
        }

        if ((options & AddressSearchOptions.PostCode) == AddressSearchOptions.PostCode)
        {
            addresses = addresses.Where(o => o.PostCode.ToUpper().Contains(search));
        }

        return addresses;
    }

而我想做的就是这个。

IEnumerable<PropertyTbl> properties = ...;

IEnumerable<PropertyTbl> filteredProperties = <use my address helper somehow>;

// this works but I need the properties as the result not just the addresses
IEnumerable<Address> filteredAddresses = AddressUtils.FilterAddresses(properties.Select(o => o.Address), "1 High Street", ...);

我可以通过将帮助程序代码直接放入正在加载/过滤属性的代码中来做我想做的事,但是我不能重用它。

任何建议表示赞赏。

【问题讨论】:

  • @leppie - 你能扩展 SelectMany 吗?我以前从未使用过它,也许这就是我所缺少的。
  • 就像from p in properties from a in p.addresses select aproperties.SelectMany(p =&gt; p.addresses)。返回IEnumerable&lt;Address&gt;。 HTH :)
  • 不使用.ToUpper().Contains(),您可以通过使用.IndexOf() 并告诉它进行不区分大小写的搜索来避免创建临时字符串:o.PostCode.IndexOf(search, StringComparison.CurrentCultureIgnoreCase) &gt;= 0

标签: c# linq filter linq-to-objects


【解决方案1】:

IEnumerable&lt;PropertyTbl&gt; 不是IEnumerable&lt;Address&gt;,因此您需要通过某种方式访问​​PropertyTableAddress 字段(除非您将BuildAddressWhereClause 更改为IEnumerable&lt;PropertyTbl&gt;

这样的事情应该可以解决问题:

public static IEnumerable<T> BuildAddressWhereClause<T>(IEnumerable<T> source, string value, AddressSearchOptions options, Func<T, Address> addressExtractor) { 
    string search = value.ToUpper(); 

    if ((options & AddressSearchOptions.Address1To4) == AddressSearchOptions.Address1To4) { 
        source = source.Where(o => addressExtractor(o).Address1.ToUpper().Contains(search) 
                                   || addressExtractor(o).Address2.ToUpper().Contains(search) 
                                   || addressExtractor(o).Address3.ToUpper().Contains(search) 
                                   || addressExtractor(o).Address4.ToUpper().Contains(search)); 
    } 

    if ((options & AddressSearchOptions.City) == AddressSearchOptions.City) { 
        source = source.Where(o => addressExtractor(o).City.ToUpper().Contains(search)); 
    } 

    if ((options & AddressSearchOptions.PostCode) == AddressSearchOptions.PostCode) { 
        source = source.Where(o => addressExtractor(o).PostCode.ToUpper().Contains(search)); 
    } 

    return source; 
} 

然后你像这样调用它

IEnumerable<PropertyTbl> properties = ...;      
IEnumerable<PropertyTbl> filteredProperties = AddressUtils.FilterAddresses(properties, "whatever", AddressSearchOptions.Whatever, p => p.Address);

【讨论】:

    猜你喜欢
    • 2014-01-08
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多