我有一个包含许多DateTime
属性的简单类:
public class MyClass
{
public DateTime Created {get; set;}
public DateTime LastChanged {get; set;}
public DateTime LastAccessed {get; set;}
...
}
稍后,在我的代码中的某个地方,我想根据这些属性过滤MyClass
的集合。对于每个属性,我想做这样的事情:
myQueryableOfMyClass = myQueryableOfMyClass.Where(a => ((begin == null) || (a.Created >= begin)) && ((end == null) || (a.Created <= end));
如果我必须为我的每个DateTime
属性执行此操作,那么很多代码会有一些拼写错误的风险,所以我想做类似的事情:
myQueryableOfMyClass = Filter(myQueryableOfMyClass, begin, end, MyClass.Created);
myQueryableOfMyClass = Filter(myQueryableOfMyClass, changebegin, changeend, MyClass.LastChanged);
myQueryableOfMyClass = Filter(myQueryableOfMyClass, accbegin, accend, MyClass.LastAccessed);
...
其中使用LINQ Filter
实现Where
方法,如第一个示例所示。
当然,上面的代码无法编译,因为MyClass.Created
是无意义的。
必须有一些使用反射的解决方案,但我对反射的经验很少。你能帮我吗?
答案 0 :(得分:4)
您可以使用Func<MyClass, DateTime>
来选择要使用的属性,例如:
public static IEnumerable<MyClass> Filter
(
IEnumerable<MyClass> myClasses,
DateTime? begin,
DateTime? end,
Func<MyClass, DateTime> selector
)
{
return myClasses.Where(a => ((begin == null) || (selector(a) >= begin)) && ((end == null) || (selector(a)) <= end));
}
您可以这样称呼它:
Filter(myClasses, begin, end, myClass => myClass.Created);
您要将myClass => myClass.Created
替换为您要使用的属性的选择器。
答案 1 :(得分:3)
我是可读代码的忠实粉丝,其中方法名称解释了他们的工作。出于这个原因,我建议添加以下方法。它们可以像我的例子一样在数据类中添加,也可以在“Filter”类中。
public class MyClass
{
public DateTime Created { get; set; }
public DateTime LastChanged { get; set; }
public DateTime LastAccessed { get; set; }
public bool WasCreatedInTimespan(DateTime? begin, DateTime? end)
{
return IsDateInTimespan(Created, begin, end);
}
public bool WasChangedInTimespan(DateTime? begin, DateTime? end)
{
return IsDateInTimespan(LastChanged, begin, end);
}
public bool WasAccessedInTimespan(DateTime? begin, DateTime? end)
{
return IsDateInTimespan(LastAccessed, begin, end);
}
private static bool IsDateInTimespan(DateTime date, DateTime? begin, DateTime? end)
{
return (!begin.HasValue || date >= begin.Value) && (!end.HasValue || date >= end.Value);
}
}
使用这些方法,调用代码变得非常清晰。像这样:
var createdList = myQueryableOfMyClass.Where(m => m.WasCreatedInTimespan(begin, end));
var changedList = myQueryableOfMyClass.Where(m => m.WasChangedInTimespan(begin, end));
var accessedList = myQueryableOfMyClass.Where(m => m.WasAccessedInTimespan(begin, end));
答案 2 :(得分:1)
创建辅助方法
public void test()
{
myQueryableOfMyClass = myQueryableOfMyClass.Where(a => Filter(begin, end, a));
}
public Boolean Filter(DateTime begin, DateTime end, DateTime date)
{
if(((begin == null) || (date >= begin)) && ((end == null) || (date <= end)))
{
return true;
}
else
{
return false;
}
}
}