在我看来,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。您仍然需要对其进行枚举以获取查询结果。