在 C# 视图中迭代枚举的对象

Iterate over objects of an Enum in C# View

我在名为 ViewDepartment.cshtml

的视图中有以下 cshtml 代码
@model DepartmentViewModel

<head>
    <meta charset="iso-8859-1">
</head>
<body>
    <div class="d-flex flex-row">
        <a class="navbar-text">@Html.DisplayNameFor(o => o.HeadOfTheDepartment): </a>
        <a class="nav-link" asp-action="Profile" asp-controller="Faculty" asp-route-Id="@Model.HeadOfTheDepartment.FacultyId">@Html.DisplayFor(o => o.HeadOfTheDepartment.FacultyName)</a>
    </div>
    @*Professors*@
    <div class="d-flex flex-column">
        <a class="navbar-text align-content-center">@Html.DisplayNameFor(o => o.Professors): </a>
        <table class="table table-bordered">
            <thead>
                <tr class="d-table-row">
                    <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyName)</th>
                    <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyDepartment)</th>
                    <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyDesignation)</th>
                    <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyAddress)</th>
                    <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyEmail)</th>
                    <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyPhoneNumber)</th>
                    <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyStatus)</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @foreach (Faculty faculty in Model.Professors)
                {
                    <tr class="d-table-row">
                        <td>@Html.DisplayFor(o => faculty.FacultyName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDepartment.DepartmentName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDesignation)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyAddress)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyEmail)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyPhoneNumber)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyStatus)</td>
                        <td><a class="nav-link" asp-action="Profile" asp-controller="Faculty" asp-route-Id="@faculty.FacultyId">View Profile</a></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    @*Associate Professors*@
    <div class="d-flex flex-column">
        <a class="navbar-text align-content-center">@Html.DisplayNameFor(o => o.AssociateProfessors): </a>
        <table class="table table-bordered">
            <thead>
                <tr class="d-table-row">
                    <th>@Html.DisplayNameFor(o => o.AssociateProfessors.First().FacultyName)</th>
                    <th>@Html.DisplayNameFor(o => o.AssociateProfessors.First().FacultyDepartment)</th>
                    <th>@Html.DisplayNameFor(o => o.AssociateProfessors.First().FacultyDesignation)</th>
                    <th>@Html.DisplayNameFor(o => o.AssociateProfessors.First().FacultyAddress)</th>
                    <th>@Html.DisplayNameFor(o => o.AssociateProfessors.First().FacultyEmail)</th>
                    <th>@Html.DisplayNameFor(o => o.AssociateProfessors.First().FacultyPhoneNumber)</th>
                    <th>@Html.DisplayNameFor(o => o.AssociateProfessors.First().FacultyStatus)</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @foreach (var faculty in Model.AssociateProfessors)
                {
                    <tr class="d-table-row">
                        <td>@Html.DisplayFor(o => faculty.FacultyName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDepartment.DepartmentName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDesignation)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyAddress)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyEmail)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyPhoneNumber)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyStatus)</td>
                        <td><a class="nav-link" asp-action="Profile" asp-controller="Faculty" asp-route-Id="@faculty.FacultyId">View Profile</a></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    @*Assistant Professors*@
    <div class="d-flex flex-column">
        <a class="navbar-text align-content-center">@Html.DisplayNameFor(o => o.AssistantProfessors): </a>
        <table class="table table-bordered">
            <thead>
                <tr class="d-table-row">
                    <th>@Html.DisplayNameFor(o => o.AssistantProfessors.First().FacultyName)</th>
                    <th>@Html.DisplayNameFor(o => o.AssistantProfessors.First().FacultyDepartment)</th>
                    <th>@Html.DisplayNameFor(o => o.AssistantProfessors.First().FacultyDesignation)</th>
                    <th>@Html.DisplayNameFor(o => o.AssistantProfessors.First().FacultyAddress)</th>
                    <th>@Html.DisplayNameFor(o => o.AssistantProfessors.First().FacultyEmail)</th>
                    <th>@Html.DisplayNameFor(o => o.AssistantProfessors.First().FacultyPhoneNumber)</th>
                    <th>@Html.DisplayNameFor(o => o.AssistantProfessors.First().FacultyStatus)</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @foreach (var faculty in Model.AssistantProfessors)
                {
                    <tr class="d-table-row">
                        <td>@Html.DisplayFor(o => faculty.FacultyName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDepartment.DepartmentName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDesignation)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyAddress)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyEmail)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyPhoneNumber)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyStatus)</td>
                        <td><a class="nav-link" asp-action="Profile" asp-controller="Faculty" asp-route-Id="@faculty.FacultyId">View Profile</a></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    @*Lecturers*@
    <div class="d-flex flex-column">
        <a class="navbar-text align-content-center">@Html.DisplayNameFor(o => o.Lecturers): </a>
        <table class="table table-bordered">
            <thead>
                <tr class="d-table-row">
                    <th>@Html.DisplayNameFor(o => o.Lecturers.First().FacultyName)</th>
                    <th>@Html.DisplayNameFor(o => o.Lecturers.First().FacultyDepartment)</th>
                    <th>@Html.DisplayNameFor(o => o.Lecturers.First().FacultyDesignation)</th>
                    <th>@Html.DisplayNameFor(o => o.Lecturers.First().FacultyAddress)</th>
                    <th>@Html.DisplayNameFor(o => o.Lecturers.First().FacultyEmail)</th>
                    <th>@Html.DisplayNameFor(o => o.Lecturers.First().FacultyPhoneNumber)</th>
                    <th>@Html.DisplayNameFor(o => o.Lecturers.First().FacultyStatus)</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @foreach (var faculty in Model.Lecturers)
                {
                    <tr class="d-table-row">
                        <td>@Html.DisplayFor(o => faculty.FacultyName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDepartment.DepartmentName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDesignation)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyAddress)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyEmail)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyPhoneNumber)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyStatus)</td>
                        <td><a class="nav-link" asp-action="Profile" asp-controller="Faculty" asp-route-Id="@faculty.FacultyId">View Profile</a></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
</body>

可以看出,对于4种不同的称谓,即Professor、AssociateProfessor、AssistantProfessor和Lecturer,都是Designation类型,是一个Enum:

public Enum Designation
{
    Professor,
    AssociateProfessor,
    AssistantProfessor,
    Lecturer
}

我必须编写相同的代码框架,即

@*Professors*@
<div class="d-flex flex-column">
    <a class="navbar-text align-content-center">@Html.DisplayNameFor(o => o.Professors): </a>
    <table class="table table-bordered">
        <thead>
            <tr class="d-table-row">
                <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyName)</th>
                <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyDepartment)</th>
                <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyDesignation)</th>
                <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyAddress)</th>
                <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyEmail)</th>
                <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyPhoneNumber)</th>
                <th>@Html.DisplayNameFor(o => o.Professors.First().FacultyStatus)</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (Faculty faculty in Model.Professors)
            {
                <tr class="d-table-row">
                    <td>@Html.DisplayFor(o => faculty.FacultyName)</td>
                    <td>@Html.DisplayFor(o => faculty.FacultyDepartment.DepartmentName)</td>
                    <td>@Html.DisplayFor(o => faculty.FacultyDesignation)</td>
                    <td>@Html.DisplayFor(o => faculty.FacultyAddress)</td>
                    <td>@Html.DisplayFor(o => faculty.FacultyEmail)</td>
                    <td>@Html.DisplayFor(o => faculty.FacultyPhoneNumber)</td>
                    <td>@Html.DisplayFor(o => faculty.FacultyStatus)</td>
                    <td><a class="nav-link" asp-action="Profile" asp-controller="Faculty" asp-route-Id="@faculty.FacultyId">View Profile</a></td>
                </tr>
            }
        </tbody>
    </table>
</div>

4次! (当然,将 Professors 更改为 Lecturers 等等)


这似乎是多余的,我想知道是否有一种方法可以让我只编写一次框架,这将 运行 用于所有 4 种类型的指定。这样,即使以后再添加 Designations,它也会自动容纳在当前代码中。

Professors(及其姊妹属性)属于IList<Faculty>类型,其中Facultyclass如下:

public class Faculty
{
    [Required]
    public string FacultyId { get; set; }
    
    [Required]
    public string FacultyName { get; set; }
    
    [Required]
    public FacultyStatus FacultyStatus { get; set; }
    
    [Required]
    public Designation FacultyDesignation { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    public string FacultyEmail { get; set; }

    [Required]
    [DataType(DataType.PhoneNumber)]
    public string FacultyPhoneNumber { get; set; }

    [Required]
    public string FacultyAddress { get; set; }
    
    [Required]
    public int FacultyExperience { get; set; }
    
    [Required]
    public string FacultyQualifications { get; set; }
    
    [Required]
    public string FacultyDescription { get; set; }

    public Department HODDepartment { get; set; }

    [ForeignKey("FacultyDepartment")]
    public string FacultyDepartmentId { get; set; }
    public Department FacultyDepartment{ get; set; }

}


我尝试了一种使用反射的方法(在 post 的先前版本中可用),但不太成功。我猜,将需要某个版本的 ForEach 循环,它将遍历 Enum.GetNames(typeof(Designation)).Cast<Designation>() 的对象。但是,我无法弄清楚我需要的反射结构,因为我对反射的概念还很陌生。我需要有人为我指明正确的方向。

我正在根据您的问题将此作为您的域名的基础。

public enum Designation
{
    professor,
    associate_professor,
    assistant_professor,
    lecturer
}

public static class ReflectionHelpers
{
    // this code can go anywhere and doesn't need to belong in your domain
    public static string GetAttributeDisplayName(PropertyInfo property)
    {
        var atts = property.GetCustomAttributes(
            typeof(DisplayNameAttribute), true);
        if (atts.Length == 0)
            return null;
        return (atts[0] as DisplayNameAttribute).DisplayName;
    }
}

public class Teacher
{
    public int FacultyId { get; }

    [DisplayName("Name")]
    public string FacultyName { get; set; }

    [DisplayName("Department")]
    public FacultyDepartment FacultyDepartment { get; set; }

    [DisplayName("Designation")]
    public string FacultyDesignation { get; set; }

    [DisplayName("Address")]
    public string FacultyAddress { get; set; }

    [DisplayName("Email")]
    public string FacultyEmail { get; set; }

    [DisplayName("Phone")]
    public string FacultyPhoneNumber { get; set; }

    [DisplayName("Status")]
    public string FacultyStatus { get; set; }
}

public class FacultyDepartment
{
    [DisplayName("Department Name")]
    public string DepartmentName { get; }
}

[AttributeUsage(AttributeTargets.Property)]
public class DesignationAttribute : Attribute
{
    public Designation Designation;

    public DesignationAttribute(Designation designation)
    {
        Designation = designation;
    }
}

public class DomainModel
{
    [DisplayName("Professors")]
    [Designation(Designation.professor)]
    public List<Teacher> Professors { get; } = new List<Teacher>();

    [DisplayName("Associate Professors")]
    [Designation(Designation.associate_professor)]
    public List<Teacher> AssociateProfessors { get; } = new List<Teacher>();

    [DisplayName("Assistant Professors")]
    [Designation(Designation.assistant_professor)]
    public List<Teacher> AssistantProfessors { get; } = new List<Teacher>();

    [DisplayName("Lecturers")]
    [Designation(Designation.lecturer)]
    public List<Teacher> Lecturers { get; } = new List<Teacher>();

    public DomainModel()
    {
        Professors.Add(new Teacher { FacultyName = "Professor 1" });
        AssociateProfessors.Add(new Teacher { FacultyName = "Associate Professor 1" });
        AssistantProfessors.Add(new Teacher { FacultyName = "Assistant Professor 1" });
        Lecturers.Add(new Teacher { FacultyName = "Lecturer 1" });
    }
}

我们这里需要的是反思。现在,我们将迭代 Enum.GetValues() 而不是 GetNames() 并根据我们分配的自定义属性找到合适的模型 属性。如果模型的属性与枚举值同名,则可以丢弃 DesignationAttribute 位。在视图中,我们基本上执行相同的循环,但立即通过反射查找我们正在使用的 属性 。 (多研究这个主题以获得更好的理解,无需在这里反省基本反思)。

我从枚举循环中已有的反射 ProperyInfo 中获取了您的主要模型 DisplayName。我通过 ReflectionHelpers 静态方法执行此操作,但您可以将此方法移动到任何地方,例如顶级库。

然后我们使用 modelProperty.GetValue(Model) 从 Model 实例中反映 属性 的值,这样我们就可以迭代 属性 的列表内容。

其余的和之前一样。

@using System.Reflection;

@model DomainModel
@{
    ViewData["Title"] = "Home Page";

    var modelProperties = Model.GetType().GetProperties();
    var teacherProperties = typeof(Teacher).GetProperties();
}

@foreach (var designation in Enum.GetValues<Designation>()) // use GetValues now
{
    var modelProperty =
        modelProperties
            .FirstOrDefault(p => p.GetCustomAttribute<DesignationAttribute>().Designation == designation);

    <div class="d-flex flex-column">
        <a class="navbar-text align-content-center">@ReflectionHelpers.GetAttributeDisplayName(modelProperty): </a>
        <table class="table table-bordered">
            <thead>
                <tr class="d-table-row">
                    @foreach (var teacherProperty in teacherProperties)
                    {
                        <th>@ReflectionHelpers.GetAttributeDisplayName(teacherProperty)</th>
                    }
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @foreach (var faculty in modelProperty.GetValue(Model) as IList<Teacher>)
                {
                    <tr class="d-table-row">
                        <td>@Html.DisplayFor(o => faculty.FacultyName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDepartment.DepartmentName)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyDesignation)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyAddress)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyEmail)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyPhoneNumber)</td>
                        <td>@Html.DisplayFor(o => faculty.FacultyStatus)</td>
                        <td>
                            <a class="nav-link" asp-action="Profile" asp-controller="Faculty" asp-route-Id="@faculty.FacultyId">View Profile</a>
                        </td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
}