5

私は以下のようなモデルを持っています:

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

usingでEngineerプロパティをレンダリングしています。View<CreateStockcheckJobModel>Html.EditorFor(m => m.Engineer, "EngineerEditor")

部分ビュー ( ) のコード内からEngineer属性 (この場合は)の値にアクセスするにはどうすればよいですか?trueEngineerEditor.ascx


以下は私のエディタコードです

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

リフレクションは認識していますが、クラスのプロパティにEngineerModel追加されたクラスに属性が追加されていないため、使用方法がわかりません。レンダリングしている をエディター コードから取得できればソートされますが、その情報を取得する方法がわかりません。クラス内のすべてのプロパティを列挙するルートをたどると、複数のプロパティがある場合に問題が発生します (1 つには の属性があり、別のプロパティには がある可能性があります)。EngineerCreateStockcheckJobModelPropertyInfoCreateStockcheckJobModelEngineerModelTrueFalse

4

2 に答える 2

7

IMetadataAwareカスタムにインターフェイスを実装することで、ASP.NET MVC 3 以降でこれを簡単に実行できEngineerAttributeます。

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明らかに、ブール値だけでなく、任意の複雑なオブジェクトをプロパティ内に配置できます。

また、メタデータについては、次の記事が役立つ場合があります。

于 2012-09-17T10:50:39.577 に答える
1

:以下はこれを行うための可能な方法ですがIMetadataAware、受け入れられた回答で説明されているように使用する方がはるかに良い方法です。可能であれば、通常は反射を避ける方がよいでしょう。

これは、リフレクションを介してのみ行うことができます。メソッド属性に対してこれを行う方法の良い例を次に示します。

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 });
于 2012-09-17T09:31:55.857 に答える