【问题标题】:Iterate over objects of an Enum in C# View在 C# 视图中迭代枚举的对象
【发布时间】:2021-12-18 01:49:00
【问题描述】:

我在名为 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的类型,它是一个枚举:

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&lt;Faculty&gt; 类型,其中Faculty 类如下:

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; }

}


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

【问题讨论】:

  • 遍历枚举“Designation”很好,因为它返回一个数组。但是“Model.designation”看起来不像一个数组。
  • @foreach (在 Enum.GetNames(typeof(Designation)).Cast()) 中指定变量

标签: c# foreach enums asp.net-core-mvc displayfor


【解决方案1】:

根据您的问题,我正在将此作为您的域类似于的基础。

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(),并根据我们分配的自定义属性找到适当的 Model 属性。如果您的模型的属性与枚举值具有相同的名称,您可以丢弃 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>
}

【讨论】:

  • 我一直在努力寻找自己的解决方案。不能说我没有靠近。但是,我采用了不同的方法(我猜这是错误的)。再问一个问题,我们也可以以某种方式概括 DisplayNameFor 函数吗?而不是o.Professors,它将使用o.&lt;whatever the current designation is here&gt;。因为,你看,使用这种方法的全部原因是能够概括 DisplayNameFor 方法的内容:)
  • 当然,答案已更新。使用相同的技术,我们也可以循环 Teacher 类型的属性。请注意,如果您有要省略的属性,则需要在视图代码中过滤 typeof(Teacher).GetProperties() 中的属性。
  • 如果你需要跳过属性的例子: var teacherProperties = typeof(Teacher).GetProperties().Where(p => new string[]{ "Hidden Property 1","Hidden Property 2" } .Contains(p.Name) == false);
  • 谢谢你!我将介绍新方法。同时,请您查看我对帖子所做的编辑并告诉我我是否走在正确的轨道上?我本质上想获取Generic.ListFirst() 方法的返回类型,然后在上面使用GetProperty,但是GetMethods()GetMethod("First") 出于某种原因继续返回null :(
  • 我可能需要看看你的实际类是什么样子才能直观地调试它。但是,您在反射代码中对我说的内容类似于“根据我的域示例找到属性 'Professors',然后,给我它的类型是 List,然后给我 List 的方法类型。但是我不确定为什么它完全为空。通过反射,尝试保存你正在做的每一步并调试它。我认为你在正确的轨道上,但在尝试得到在这种情况下,属性的类型的方法,有一个更快的路线(我的呵呵)。
猜你喜欢
  • 2018-09-07
  • 1970-01-01
  • 2011-06-19
  • 2022-12-05
  • 2015-03-24
  • 2010-09-18
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多