-2

我有以下声明:

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

3 回答 3

2

您的问题非常不清楚,但是该let子句可以让您分解子表达式结果。可能是这个(?):

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

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

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

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

于 2012-06-13T13:35:57.403 回答
2

在我看来,Variable 只是一个稍后定义的变量。如果你真的想让你的表达式像这样可以修改,你最好的选择是使用反射。

首先,您需要获取对所需属性的 PropertyInfo 的引用。您可以通过调用Type.GetProperty(string name)来做到这一点。获得对 PropertyInfo 的引用后,您可以通过调用PropertyInfo.GetValue(Object obj, Object[] index)来获取特定实例的值。

下面是一个创建 LINQ 查询的示例,该查询将仅获取指定属性不为空的项目。

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

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

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

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

于 2012-06-13T14:03:23.047 回答
0

如果我正确理解了您的问题,您想Country用动态的东西替换硬编码字段。

在这种情况下,您需要声明Variable(让我们改为调用它getNotNullField)作为函数 from ListItemto object

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;   
于 2012-06-13T13:37:58.790 回答