简体   繁体   English

将属性名称作为参数传递

[英]Pass property name as parameter

I have the following class我有以下课程

public class School
{
    public List<Student> Students { get; set; }
    public List<Teacher> Teachers { get; set; }
}

Now i have this method现在我有了这个方法

public bool Evaluate(??)
{
    var school = DbContext.Schools.FirstOrDefault();
    return school.??.Any(/*some expresions*/)
}

I should be able to pass a value in ??我应该能够在 ?? and use it so that i can use both并使用它以便我可以同时使用

return school.Students.Any(/*some expresions*/)
return school.Teachers.Any(/*some expresions*/)

So how can i replace the question marks with Students or Teachers ?那么如何用学生或教师替换问号?

Edit:编辑:

public class Student 
{
    public string FullName { get; set; }
    public bool Registered { get; set; }
    public bool Passed { get; set; }
}

public class Teacher
{
    public string FullName { get; set; }
    public bool CanEvaluate { get; set; }
    public bool Validator { get; set; }
}


public class DynamicCheckTest
{
    public bool MyExpression<T>(List<T> items, string name,
        Expression<Func<T, bool>> expression)
    {
        return items.Any(x => expression.Compile()(x));
    }
}

public static bool Check<T>(this List<T> items, Func<T, bool> compiledExp)
{
    return items.Any(x => compiledExp(x));
}

Students.Check(x => x.Name == "Mike" &&  x.Registered); // example
Teachers.Check(x => x.Name == "Jack" &&  x.CanEvaluate);// example

Now i have to pass the school along which contains both Students and Teachers But i don't know which one will be called in advance现在我要经过学校,里面有学生和老师,但我不知道会提前打电话给哪一个

Addressing the "Pass property name as parameter" request, you could use reflection for that, but I don't think that's a good way to go.解决“将属性名称作为参数传递”请求,您可以为此使用反射,但我认为这不是一个好方法。 Instead, a Func<School, List<TElement>> could be used to select the desired List<> property to evaluate...相反,可以使用Func<School, List<TElement>>来选择所需的List<>属性来评估...

public bool Evaluate<TElement>(Func<School, List<TElement>> listSelector)
    where TElement : Person
{
    School school = DbContext.Schools.FirstOrDefault();
    DateTime today = DateTime.Today;

    return listSelector(school)
        // For example, check if today is the birthday of anyone in the selected list
        .Any(person => person.DateOfBirth.Month == today.Month && person.DateOfBirth.Day == today.Day);
}

As @Enigmativity points out, the type constraint is necessary in order to pass much of a meaningful condition to Any() , which also assumes/requires that Student and Teacher have common ancestry, like this...正如@Enigmativity 指出的那样, 类型约束是必要的,以便将许多有意义的条件传递给Any() ,这也假设/要求StudentTeacher具有共同的祖先,像这样......

public abstract class Person
{
    public DateTime DateOfBirth
    {
        get;
    }
}

public class Student : Person
{
}

public class Teacher : Person
{
}

You'd then use a lambda expression to specify the desired List<> ...然后,您将使用lambda 表达式来指定所需的List<> ...

bool isAnyStudentsBirthday = Evaluate(school => school.Students);
bool isAnyTeachersBirthday = Evaluate(school => school.Teachers);

This will work as long as the members you want Any() to consider are available in the constrained type (ie Person ).只要您希望Any()考虑的成员在约束类型(即Person )中可用,这就会起作用。 If you wanted to filter using members specific to the Student or Teacher class, your best bet would be to use an approach like @Enigmativity's answer , where the filter itself is a parameter and receives the same derived type as the selected List<> stores.如果您想使用特定于StudentTeacher类的成员进行过滤,最好的办法是使用类似@Enigmativity's answer 的方法,其中过滤器本身是一个参数,并接收与所选List<>存储相同的派生类型。

Note that if you ever want to use Evaluate() with some other collection property of School that is not specifically List<> , or just knowing that all Any() needs is an IEnumerable<> , you could change the return type (last type parameter ) of the Func<> to something less-restrictive...请注意,如果您想将Evaluate()School一些其他集合属性一起使用,这些属性不是专门为List<> ,或者只是知道Any()需要的是一个IEnumerable<> ,您可以更改返回类型(最后一个类型Func<> 参数) 改为限制较少的内容...

Func<School, IList<TElement>>
Func<School, ICollection<TElement>>
Func<School, IEnumerable<TElement>>

You could use this method:你可以使用这个方法:

public bool Evaluate<T>(Func<School, List<T>> project, Func<T, bool> filter)
{
    var school = DbContext.Schools.FirstOrDefault();
    return project(school).Any(filter);
}

If we assume that the implementation of Student and Teacher are this:如果我们假设StudentTeacher的实现是这样的:

public class Student
{
    public string Name;
}

public class Teacher
{
    public string Subject;
}

Then you could do this:那么你可以这样做:

bool hasFred = Evaluate(school => school.Students, student => student.Name == "Fred Nerk");
bool teachArt = Evaluate(school => school.Teachers, teacher => teacher.Subject == "Art");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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