【问题标题】:How to access C# model attribute within EditorFor如何在 EditorFor 中访问 C# 模型属性
【发布时间】:2012-09-09 12:05:28
【问题描述】:

我有一个如下模型:

public class CreateStockcheckJobModel
{
    [Engineer(true)]
    public EngineerModel Engineer { get; set; }
}

我正在使用Html.EditorFor(m => m.Engineer, "EngineerEditor")View<CreateStockcheckJobModel> 中呈现Engineer 属性。

如何从部分视图 (EngineerEditor.ascx) 的代码中访问 Engineer 属性中的值(在本例中为 true)?


下面是我的编辑器代码

<%@ Control Language="C#" Inherits="ViewUserControl<EngineerModel>" %>
<% if (PropertyImRenderingHasAttributeWithTrueBooleanValue) // What goes here?
   { %>
<p>Render one thing</p>
<% }
   else
   { %>
<p>Render another thing</p>
<% } %>

我知道反射,但是我不确定如何使用它,因为该属性未添加到 EngineerModel 类中,而是添加到 CreateStockcheckJobModel 类的 Engineer 属性中。如果我能得到我正在从编辑器代码中渲染的PropertyInfo,那么我会被排序,但我不知道如何获取该信息。如果我沿着枚举CreateStockcheckJobModel 类中的所有属性的路线走,那么如果我有多个EngineerModel 属性(一个可能有True 的属性,另一个可能有@987654336 @)。

【问题讨论】:

  • 你想得到什么?在我看来,你做错了实现你的目标
  • 它基本上呈现了一个可供选择的工程师列表。我希望该属性控制可用工程师的列表。
  • 我认为这是一个合理的方法,因为它似乎是 DisplayFormat 属性正在做的事情(即根据属性中的数据更改控件/编辑器的呈现方式)

标签: c# asp.net-mvc-2 partial-views


【解决方案1】:

注意:以下是一种可能的方法,但使用接受的答案中描述的IMetadataAware 是一种更好的方法。如果可以的话,通常最好避免反思。

您只能通过反射来做到这一点。这是一个good example,关于如何为方法属性执行此操作。

获取EngineerAttribute 属性Engineer 的值的代码示例:

PropertyInfo pi = Model.GetType().GetProperty("Engineer");
EngineerAttribute a =
    System.Attribute.GetCustomAttribute(pi, typeof(EngineerAttribute));

获取具有[Engineer(true)]属性的所有属性的代码示例:

var t = Model.GetType();
var engineerProperties =
    from p in t.GetProperties()
    let ca = System.Attribute.GetCustomAttribute(p, typeof(EngineerAttribute))
    where ca != null && ca.BooleanProperty == true
    select p;

当你拥有这些属性时,你可以使用EditorFor 的重载,它允许你指定额外的视图数据,然后你可以在你的子视图中使用:

Html.EditorFor(m => m.Engineer, new { IsEngineer = isEngineer });

【讨论】:

  • 我知道反射是如何工作的,但我无法确定要获取属性的属性,因为在编辑器中我只有类型 EngineerModel 而不是封闭类型和属性(即该属性不在EngineerModel 上,而在恰好是EngineerModel 的属性上。
  • 鉴于您的编辑,我的问题是在编辑器中模型的类型为 EngineerModel 并且属性不在模型上,而是在封闭模型的属性上。显然,属性名称可能会改变,并且EngineerModel 类型可能有多个属性(所以我不能只获取封闭模型类型并找到EngineerModel 类型的属性)。
  • 我刚刚阅读了有关问题的 cmets,您真正想要的是列出所有具有 [Engineer(true)] 的属性?
  • 啊,现在我明白了您想要什么...您不再有权访问定义属性的根模型...我认为您想要的不可能。你不能向 EngineerModel 添加一个属性来表达工程师的“工程”而不是应用自定义属性吗?
  • 一旦我拥有了具有该属性的所有属性,我如何知道编辑器应该渲染哪一个? (如果我有多个EngineerModel 类型的属性,每个属性都有自己的Engineer 属性。
【解决方案2】:

这可以通过在您的自定义EngineerAttribute 上实现IMetadataAware 接口在 ASP.NET MVC 3 及更高版本中轻松完成:

public class EngineerAttribute : Attribute, IMetadataAware
{
    public EngineerAttribute(bool isFoo)
    {
        IsFoo = isFoo;
    }

    public bool IsFoo { get; private set; }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["IsFoo"] = IsFoo;
    }
}

然后在模板里面:

<%@ Control Language="C#" Inherits="ViewUserControl<EngineerModel>" %>
<%
    var isFoo = (bool)ViewData.ModelMetadata.AdditionalValues["IsFoo"];
%>
<% if (isFoo) { %>
    <p>Render one thing</p>
<% } else { %>
    <p>Render another thing</p>
<% } %>

不幸的是,ASP.NET MVC 2 中不存在此接口。要实现相同的功能,您可以编写自定义元数据提供程序:

public class MyMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes, 
        Type containerType, 
        Func<object> modelAccessor, 
        Type modelType, 
        string propertyName
    )
    {
        var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        var engineer = attributes.OfType<EngineerAttribute>().FirstOrDefault();
        if (engineer != null)
        {
            metadata.AdditionalValues["IsFoo"] = engineer.IsFoo;
        }
        return metadata;
    }
}

您将在Application_Start 中注册以替换默认的:

ModelMetadataProviders.Current = new MyMetadataProvider();

现在您可以使用ViewData.ModelMetadata.AdditionalValues["IsFoo"] 以与我之前展示的相同方式在模板中访问此元数据。显然,您可以在 AdditionalValues 属性中放置一个任意复杂的对象,而不仅仅是布尔值。

您还可能会发现following article 对元数据很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-10
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 2012-12-19
    相关资源
    最近更新 更多