[英]Reference to a property of class in predicate using reflection
I have a simple class with many DateTime
properties: 我有一个带有许多
DateTime
属性的简单类:
public class MyClass
{
public DateTime Created {get; set;}
public DateTime LastChanged {get; set;}
public DateTime LastAccessed {get; set;}
...
}
Later, somewhere in my code I would like to filter collection of MyClass
based on these properties. 稍后,在我的代码中的某个地方,我想根据这些属性过滤
MyClass
的集合。 For each property I would like to do something like this: 对于每个属性,我想执行以下操作:
myQueryableOfMyClass = myQueryableOfMyClass.Where(a => ((begin == null) || (a.Created >= begin)) && ((end == null) || (a.Created <= end));
If I had to do this for each of my DateTime
property, it would be a lot of code with some risk of a typo, so I would like to do something like this: 如果我必须为每个
DateTime
属性执行此操作,则可能会有很多代码有输入错误的风险,因此我想执行以下操作:
myQueryableOfMyClass = Filter(myQueryableOfMyClass, begin, end, MyClass.Created);
myQueryableOfMyClass = Filter(myQueryableOfMyClass, changebegin, changeend, MyClass.LastChanged);
myQueryableOfMyClass = Filter(myQueryableOfMyClass, accbegin, accend, MyClass.LastAccessed);
...
where the Filter
method is implemented using the LINQ Where
as in the first example. 与第一个示例一样,使用LINQ
Where
实现了Filter
方法。
The code above does not compile, of course, because MyClass.Created
is a nonsense. 当然,上面的代码不会编译,因为
MyClass.Created
是胡说八道。
There must be some solution using reflection, but I have little very experience with reflection. 必须有一些使用反射的解决方案,但是我对反射的经验很少。 Could you please help me?
请你帮助我好吗?
You could use a Func<MyClass, DateTime>
to choose which property to use, like so: 您可以使用
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));
}
You'd call it like this: 您可以这样称呼它:
Filter(myClasses, begin, end, myClass => myClass.Created);
Where you would replace myClass => myClass.Created
with a selector for the property you want to use. 使用要选择的属性的选择器替换
myClass => myClass.Created
。
I am a big fan of readable code where method names explain what they do. 我是可读代码的忠实拥护者,其中方法名称解释了它们的作用。 For that reason I would suggest adding the following methods.
因此,我建议添加以下方法。 They could be either added in the data class itself as in my example or they could be in a "Filter" class.
可以像我的示例一样将它们添加到数据类本身中,也可以将它们添加到“ 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);
}
}
With these methods, the calling code becomes very clear. 使用这些方法,调用代码变得非常清晰。 Like so:
像这样:
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));
Create a helper method 创建一个辅助方法
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;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.