【问题标题】:How to expand object to primitive properties using linq如何使用 linq 将对象扩展为原始属性
【发布时间】:2017-08-25 04:43:35
【问题描述】:

假设我有以下课程:

public class StudentTeacher
{
public Student Student {get; set;}   
public Teacher Teacher {get; set;}   
public int OverlappingClasses {get; set;}
}

现在,在我的代码中,我有一个对象列表。

List<StudentTeacher> studentTeacher = GetStudentTeachers();   

现在,我需要选择所有属性作为属性而不是对象。

例如,我可以这样做:studentTeacher.Select(x=&gt;x.Student),它会返回一个对象列表(IEnumerable)。

但是当我选择多个属性时,即 studentTeacher.Select(x=> new {x.Student, x.Teacher}).ToList() 返回类型是IEnumerable {Anonymous {Student, Teacher}}

如何,而不是这种复杂的匿名类型,我可以有一个只有属性的简单匿名类型。 (所以,它将是Anonymous{StudentID, StudentName, StudentLastName, TeacherID, TeahcerName, TeacherLastName, etc.}

一种方法是在 select 子句中明确指定所有属性,但在我的特定用例中,每个对象都有 >30 个属性,并且属性总数 >100。)

【问题讨论】:

  • 可能有一种方法可以使用反射来做到这一点,我不知道。但是这两个类中是否有任何同名的属性?
  • 您的意思是要将对象扁平化为单个匿名类型?所以 Student.Id 会变成 StudentId 等等?如果是这样,您打算如何处理引用循环?
  • 为什么不创建 DTO 并使用 AutoMapper?

标签: c# .net linq


【解决方案1】:

我认为这就是你想要做的:

    public class Student
    {
        public int StudentId
        {
            get;
            set;
        } = 1;

        public string StudentName
        {
            get;
            set;
        } = "Name";
    }

    public class Teacher
    {
        public int TeacherId
        {
            get;
            set;
        } = 666;

        public string TeacherName
        {
            get;
            set;
        } = "TeacherName";
    }

    public class StudentTeacher
    {
        public Student Student
        {
            get;
        } = new Student();

        public Teacher Teacher
        {
            get;
        } = new Teacher();
    }

    public static dynamic GetAnonType(Student student, Teacher teacher)
    {
        var propertyNamesAndPropertiesStudent = student.GetType().GetProperties().Select(item => Tuple.Create($"{nameof(Student)}{item.Name}", item.GetMethod.Invoke(student, null)));
        var propertyNamesAndPropertiesTeacher = teacher.GetType().GetProperties().Select(item => Tuple.Create($"{nameof(Teacher)}{item.Name}", item.GetMethod.Invoke(teacher, null)));
        dynamic sampleObject = new ExpandoObject();
        foreach(var propertyNamePropertyValuePair in propertyNamesAndPropertiesStudent)
        {
            ((IDictionary<string, object>)sampleObject).Add(propertyNamePropertyValuePair.Item1, propertyNamePropertyValuePair.Item2);
        }

        foreach(var propertyNamePropertyValuePair in propertyNamesAndPropertiesTeacher)
        {
            ((IDictionary<string, object>)sampleObject).Add(propertyNamePropertyValuePair.Item1, propertyNamePropertyValuePair.Item2);
        }

        return sampleObject;
    }

你可以这样称呼:

        var studentTeachers = new List<StudentTeacher> {new StudentTeacher()};
        var anonTypes = studentTeachers.Select(item => GetAnonType(item.Student, item.Teacher));

anonTypes 将是匿名类型的可枚举,其成员包括 StudentId、StudentName、TeacherId、TeacherName。这应该扩展到更大的对象。

【讨论】:

    【解决方案2】:
    studentTeacher.Select(x=> new 
    {x.Student.StudentID, x.Student.StudentName, x.Student.StudentLastName, x.Teacher.TeacherID, x.Teacher.TeahcerName, x.Teacher.TeacherLastName, etc.})
    

    它将使用属性名称作为对象内部的名称,即 Student = x.Student.StudentID 也可以直接赋值 例如

    studentTeacher.Select(x=> new 
    { StudentID = x.Student.StudentID, x.Student.StudentName, x.Student.StudentLastName, x.Teacher.TeacherID, x.Teacher.TeahcerName, x.Teacher.TeacherLastName, etc.})
    

    【讨论】:

    • OP 提到他已经知道这一点并想知道它是否可以动态完成。
    【解决方案3】:

    如果你有很多属性,为什么不选择整个类?

    IEnumerable<StudentTeacher> studentTeachers = GetStudentTeachers();
    IEnumerable<StudentTeacher> femaleTeachers = studentTeachers
        .Where(teacher => teacher.IsFemale);
    

    现在您不必提及所有属性。这也适用于连接:

    var TeachersWithTheirStudents = studentTeachers.GroupJoin(students,
        teacher => teacher.Id,
        student => student.TeacherId,
        (teacher, students) => new
        {
            Teacher = teacher,
            HisStudents = students,
        }
    

    换句话说:组加入TeachersStudents 的集合。从每个Teacher 获取Id。取所有Students 和一个等于IdTeacherId,从这个Teacher 和他所有的Students 组成一个具有属性TeacherHisStudents 的匿名对象

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-18
      相关资源
      最近更新 更多