LINQ哪里有变量

时间:2012-06-13 13:33:46

标签: c# linq

我有以下声明:

var itemsFromList = from item in ListItems 
                    where item.Countries != null 
                    select item;

因此,我可以返回国家/地区中存在的所有值(有些值为空)。 在同一个列表中,我有其他列,例如城市,我必须将其更改为:

var itemsFromList = from item in ListItems 
                    where item.cities != null 
                    select item;

有没有办法使用相同的语句通过使用变量来返回非空的城市或国家:

var itemsFromList = from item in ListItems 
                    where item.variable != null 
                    select item;

3 个答案:

答案 0 :(得分:2)

你的问题很不清楚,但是let子句可以让你打破子表达式结果。可能是这个(?):

var itemsFromList = from item in ListItems 
                    let Variable = item.Countries
                    where Variable != null 
                    select item;

我不确定这实际上会实现什么。

我唯一的另一个想法是你在编译时不知道Variable是什么,想要注入什么东西?

正如@DarenThomas所说,如果Variable实际上是Linq语句的外部,整个语句就会失效,因为Variable在每次迭代时都不会发生变化。

答案 1 :(得分:2)

在我看来,变量只是一个变量,它是在以后定义的。如果你真的希望你的表达可以像这样修改,你最好的选择是使用Reflection。

首先,您需要获取所需属性的PropertyInfo的引用。您可以致电Type.GetProperty(string name)来完成此操作。获得PropertyInfo的引用后,您可以通过调用PropertyInfo.GetValue(Object obj, Object[] index)来获取特定实例的值。

以下是创建LINQ查询的示例,该查询仅获取指定属性不为null的项。

// Declare this as a Generic method of Type T so that we can pass in a
// List containing anything and easily get the appropriate Type object
public static IEnumerable<T> SelectNonNull<T>(
    IEnumerable<T> ListItems, string propertyName)
{
    IEnumerable<T> itemsFromList;
    // Get a reference to the PropertyInfo for the property
    // we're doing a null-check on.
    PropertyInfo variable = typeof(T).GetProperty(propertyName);
    if (variable == null)
    {
        // The property does not exist on this item type:
        // just return all items
        itemsFromList = from item in ListItems
                        select item;
    }
    else
    {
        itemsFromList = from item in ListItems
                        // GetValue will check the value of item's
                        // instance of the specified property.
                        where variable.GetValue(item, null) != null
                        select item;
    }
    return itemsFromList;
}

要在问题中得到结果,您可以像这样使用此函数:

var NonNullCountries = SelectNonNull(ListItems, "Countries");
var NonNullCities = SelectNonNull(ListItems, "cities");

或者,我们可以将此声明为扩展方法(与其他Linq方法一样),如下所示:

public static IEnumerable<T> SelectNonNull<T>(
    this IEnumerable<T> source,
    string propertyName)
{
    PropertyInfo variable = typeof(T).GetProperty(propertyName);
    if (variable == null)
    {
        // Specified property does not exist on this item type:
        //just return all items
        return from item in source
                select item;
    }
    else
    {
        return from item in source
                where variable.GetValue(item, null) != null
                select item;
    }
}

然后我们可以将多个呼叫链接在一起。例如,如果您想过滤掉“cities”和“Countries”为空的所有条目,您可以使用以下内容:

var NonNullCitiesOrCountries = ListItems.SelectNonNull("Countries")
                                        .SelectNonNull("cities");

注意: SelectNonNull只返回一个IEnuerable。您仍然需要枚举它以获取查询结果。

答案 2 :(得分:0)

如果我正确理解了您的问题,您希望将硬编码字段Country替换为动态内容。

在这种情况下,您需要将Variable(让我们称之为getNotNullField)声明为ListItemobject的函数:

Func<ListItem, object> getNotNullField;
if (...) {
    getNotNullField = item => item.Countries;
} else {
    getNotNullField = item => item.SomeOtherField;
}

...

var itemsFromList = from item in ListItems where getNotNullField(item) != null 
                    select item;