传递属性名称作为参数

时间:2020-02-29 01:32:15

标签: c#

我有以下课程

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

现在我有此方法

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

我应该能够在??中传递一个值并使用它,以便我可以同时使用

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

那么我该如何用学生或老师替换问号?

编辑:

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

现在我必须通过既有学生又有老师的学校 但是我不知道会提前打电话给谁

2 个答案:

答案 0 :(得分:2)

解决“将属性名称作为参数传递”的请求,您可以使用反射,但是我认为这不是一个好方法。相反,可以使用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);
}

正如@Enigmativity指出的那样,type constraint对于将很多有意义的条件传递给Any()是必要的,Student还假定/要求Teacherpublic abstract class Person { public DateTime DateOfBirth { get; } } public class Student : Person { } public class Teacher : Person { } 有共同的血统,像这样...

List<>

然后您将使用lambda expression指定所需的bool isAnyStudentsBirthday = Evaluate(school => school.Students); bool isAnyTeachersBirthday = Evaluate(school => school.Teachers); ...

Any()

只要您希望Person考虑的成员以受约束的类型(即Student)可用,此方法就会起作用。如果您想使用特定于TeacherList<>类的成员进行过滤,则最好的选择是使用类似@Enigmativity's answer的方法,其中过滤器本身是一个参数并接收相同的参数派生类型作为选定的Evaluate()存储。

请注意,如果您想将SchoolList<>的某些其他集合属性一起使用,而这些属性不是专门为Any()而设计的,或者只是知道所有IEnumerable<>的需求就是Func<>,您可以将Func<School, IList<TElement>> Func<School, ICollection<TElement>> Func<School, IEnumerable<TElement>> 的返回类型(最后type parameter)更改为限制较少的内容...

function sell_below10() {
    return Close < HHV(High,20) * 0.9;
}

function sell_abv10() {
    return Close < HHV(High,20) * 0.8;
}

Buy = Cross(Close, MA(Close, 50));

openPrice = Ref(Close, -BarsSince(Buy));
pctChange = IIf(openPrice == 0, 0, (openPrice - Close) / openPrice) * 100;

Sell = IIf(pctChange > 10, sell_abv10(), IIf(pctChange < 10, sell_below10(), False));

答案 1 :(得分:2)

您可以使用此方法:

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

如果我们假设StudentTeacher的实现是这样的:

public class Student
{
    public string Name;
}

public class Teacher
{
    public string Subject;
}

然后您可以执行以下操作:

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