简体   繁体   English

使用反射在谓词中引用类的属性

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM