我有List<Device>
。在Device
类中有4个属性,即Name
,OperatingSystem
,Status
和LastLoggedInUser
。我需要写一个方法:
IQueryable<Device> FilterDeviceList(
List<Device> Devices,
List<string> filter,
string filterValue)
其中filter
将包含用于过滤"name"
,"os"
的选项,以指示要包含在搜索中的字段。如果传递"all"
,则需要包含所有4个字段。
filtervalue
将包含要过滤的值,例如"windows"
,"Calvin"
。
有人可以建议一种方法来实现这个目标吗?
编辑:
如果我不清楚,我的过滤方式有点像这样,它是我需要代码的注释部分。
if(filter.contains(name))
{
//filter with name
}
if( filter.contains(both name and os)
{
// I only need the filter value to contain in name or OS (only needed in any one of the field,not necessary to be in both)
}`
答案 0 :(得分:12)
您可以按如下方式构建查询:
private static IQueryable<Device> FilterDeviceList(List<Device> devices, Device device)
{
var query = devices.AsQueryable();
if (device.Name != null)
query = query.Where(d => d.Name == device.Name);
if (device.OS != null)
query = query.Where(d => d.OS == device.OS);
if (device.Status != null)
query = query.Where(d => d.Status == device.Status);
if (device.LastLoggedInUser != null)
query = query.Where(d => d.LastLoggedInUser == device.LastLoggedInUser);
return query;
}
然后您可以使用设备对象调用此函数。即如果要包含名称,只需传递带有名称的设备对象(将其他属性保留为默认值)。如果您希望包含所有内容,请传入一个包含所有内容的设备对象:
var r = FilterDeviceList(devices, new Device
{
Name = "yourFilterValue",
OS = "yourFilterValue",
LastLoggedInUser = "yourFilterValue",
Status = "yourFilterValue"
});
编辑,过滤名称属性:
var r = FilterDeviceList(devices, new Device
{
Name = "yourFilterValue"
});
编辑2,查看predicatebuilder
var predicate = PredicateBuilder.False<Device>();
if(document.Name != null)
predicate = predicate.Or(d => d.Name == document.Name);
if(document.OS != null)
predicate = predicate.Or(d => d.OS == document.OS);
return devices.Where(predicate);
答案 1 :(得分:6)
你可以这样做:
public IEnumerable<Device> FilterDevices(IEnumerable<Device> devices, IEnumerable<Func<Device, string>> filters, string filterValue)
{
foreach (var filter in filters)
{
devices = devices.Where(d => filter(d).Equals(filterValue));
}
return devices;
}
使用:
public class Device
{
public string Name { get; set; }
public string OS { get; set; }
}
用法:
var devices = new List<Device>
{
new Device { OS = "Windows", Name = "Foo" },
new Device { OS = "Mac", Name = "Bar" }
};
var filters = new List<Func<Device, string>>
{
d => d.OS
};
var result = FilterDevices(devices, filters, "Windows");
这只是一个粗略的想法 - 根据需要转换为您的解决方案!
答案 2 :(得分:0)
你基本上有两个选择:
Func<TObject, TFilterValue, bool>
谓词之间的映射进行硬编码。您可以在静态字典(或普通旧字典)中执行此操作。只需确保在谓词上创建闭包并绑定过滤器值。 Where调用需要Func<T, bool>
答案 3 :(得分:0)
private IQueryable<Device> FilterCentraStageDeviceList(List<Device> centraStageDevices, string filter, string filterValue)
{
IQueryable<Device> alldevices = centraStageDevices.AsQueryable<Device>();
IQueryable<Device> query = new List<Device>().AsQueryable();
if (filter == null || string.IsNullOrEmpty(filterValue))
{
return alldevices;
}
filterValue = filterValue.ToLower();
var filterLower = filter.ToLower();
if (filterLower.Contains("all") || (filterLower.Contains("hostname") && filterLower.Contains("operatingsystem") && filterLower.Contains("status") && filterLower.Contains("lastloggedinuser")))
{
return alldevices.Where(x => checkNull(x.Name).Contains(filterValue) || checkNull(x.OperatingSystem).Contains(filterValue) || checkNull(x.LastUser).Contains(filterValue));
}
if (filterLower.Contains("hostname"))
{
query = alldevices.Where(x => checkNull(x.Name).Contains(filterValue));
}
if (filterLower.Contains("operatingsystem"))
{
query = alldevices.Where(x => checkNull(x.OperatingSystem).Contains(filterValue)).Union(query);
}
if (filterLower.Contains("lastloggedinuser"))
{
query = alldevices.Where(x => checkNull(x.LastUser).Contains(filterValue)).Union(query);
}
return query;
}
这是我最后使用的,因为我不允许使用外部dll,即使谓词构建器是我的场景的适当解决方案。