【问题标题】:Retrieve model name in custom display name attribute在自定义显示名称属性中检索模型名称
【发布时间】:2016-07-26 14:54:12
【问题描述】:

这是我的开发需求,

我的标签值存储在数据库中,我仍然想以声明的方式使用数据注释,这是为了让我的模型更具可读性。

这是我的方法,

我决定编写自定义 DisplayNameAttribute,其中我的模型提供的默认值将被从数据库中检索到的值覆盖。

这里是模型中定义的属性,

    [CustomDisplay(Name: "First Name")]
    [CustomRequired(ErrorMessage: "{0} is required")]
    public String FirstName { get; set; }

这里是自定义显示名称属性类,

public class CustomDisplayAttribute : DisplayNameAttribute
{
    private string _defaultName;
    private string _displayName;

    public CustomDisplayAttribute(string Name)
    {
        _defaultName = Name;
    }

    public override string DisplayName
    {
        get
        {
            if (String.IsNullOrEmpty(_displayName))
            {
                _displayName = DAO.RetrieveValue(**ModelName**, _defaultName);
            }
            return _displayName;
        }
    }
}

现在,您可以在上面的代码中看到,ModelName 是我需要的,但我没有!

在调试时,我深入研究了 ModelMetadataProviders.Current,可以看到当前模型在运行中的可用性。但是,由于它是非公共静态成员的一部分,我无法通过我的代码访问它。

我已经编写了下面的方法来通过反射检索模型名称,

private static string GetModelName()
{
    var modelName = String.Empty;
    FieldInfo info = typeof(CachedAssociatedMetadataProvider<CachedDataAnnotationsModelMetadata>)
                        .GetField("_typeIds", BindingFlags.NonPublic | BindingFlags.Static);
    var types = (ConcurrentDictionary<Type, string>)info.GetValue(null);
    modelName = types.FirstOrDefault().Key.Name;
    return modelName;
}

但问题是,类型集合为我提供了所有模型的条目(用户至少访问过一次)。而且没有任何线索知道,目前正在行动!!

【问题讨论】:

    标签: asp.net-mvc-3 data-annotations modelmetadataprovider displayname-attribute


    【解决方案1】:

    恕我直言,属性应该用于进行数据库调用。应该使用属性将元数据添加到类/属性等...

    因此,如果您愿意将代码更改为更像 Microsoft 的 MVC 架构,那么您将拥有自定义 Attribute 和自定义 ModelMetadataProvider:

    public class CustomDisplayAttribute : Attribute
    {
        public CustomDisplayAttribute(string name)
        {
            Name = name;
        }
    
        public string Name { get; private set; }
    }
    

    然后是一个新的 ModelMetadataProvider:

    public class DatabaseModelMetadataProvider : DataAnnotationsModelMetadataProvider
    {
      public DatabaseModelMetadataProvider()
      {
      }
    
      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 displayAttribute = containerType == null
            ? null as CustomDisplayAttribute
            : containerType.GetProperty(propertyName)
               .GetCustomAttributes(false)
               .OfType<CustomDisplayAttribute>()
               .FirstOrDefault();
        if (displayAttribute != null)
        {
          var displayValue = DAO.RetrieveValue(containerType.ToString(), displayAttribute.Name)
    
          metadata.DisplayName = displayValue;
        }
        return metadata;
      }
    }
    

    在哪里

    public class MyViewModel
    {
      public MyPropertyType PropertyName { get; set; }
    }
    
    • containerType = MyViewModel
    • modelType = MyPropertyType
    • propertyName = PropertyName

    然后注册提供者(global.asax 或其他):

    ModelMetadataProviders.Current = new LocalizedModelMetadataProvider();
    

    您还可以查看ModelMetadata,它还有一些您将来可能想要更改的其他内容。

    【讨论】:

      猜你喜欢
      • 2021-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多