自定义 DisplayFormatAttribute 只设置一次
Customized DisplayFormatAttribute only setting once
我通过以下代码在资源的 DisplayFormat 中设置 NullDisplayText
public class LocalizedDisplayFormatAttribute : DisplayFormatAttribute
{
private readonly PropertyInfo _propertyInfo;
public LocalizedDisplayFormatAttribute(string resourceKey, Type resourceType)
: base()
{
this._propertyInfo = resourceType.GetProperty(resourceKey, BindingFlags.Static | BindingFlags.Public);
if (this._propertyInfo == null)
{
return;
}
base.NullDisplayText = (string)this._propertyInfo.GetValue(this._propertyInfo.DeclaringType, null);
}
public new string NullDisplayText
{
get
{
return base.NullDisplayText;
}
set
{
base.NullDisplayText = value;
}
}
}
我使用的默认区域性是 "en-US",一旦我将区域性更改为 es-AR 并加载页面,它就可以正常工作,但是当我将区域性更改回 en-US 时,字段不会转换回来.
我通过以下方式改变文化
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
try
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
CultureInfo ci = new CultureInfo(culutureCode);
System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
System.Threading.Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(ci.Name);
}
catch
{
}
}
我在 ViewModel 中使用 DisplayFormat 属性作为
public class AlarmCodeDetailsViewModel
{
/// <summary>
/// Gets or sets the alarm code ID
/// </summary>
public int AlarmCodeID { get; set; }
/// <summary>
/// Gets or sets the alarm code
/// </summary>
[LocalizedDisplayName("Label_AlarmCode")]
[LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)]
public string Code { get; set; }
/// <summary>
/// Gets or sets the Description
/// </summary>
[LocalizedDisplayName("Label_Description")]
[LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)]
public string Description { get; set; }
/// <summary>
/// Gets or sets the Notes
/// </summary>
[LocalizedDisplayName("Label_Notes")]
[LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)]
public string Notes { get; set; }
}
这里有一些问题的见解。
Mvc 使用一种类型描述符 (AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type)
) 来读取模型的属性。 TypeDescriptors 缓存有关特性和特性的信息。因此,就 TypeDescriptor api 而言,您的 LocalizedDisplayFormatAttribute
属性仅被实例化一次,这意味着资源信息仅被读取一次(在构造时)。请参阅答案的底部以供参考。
无效的解决方案
眨眼反应是每次通过getter访问时,只从您的LocalizedDisplayFormatAttribute NullDisplayText
中提取最新的资源信息。不幸的是 DisplayFormatAttribute
NullDisplayText
不是虚拟的,您正在用 new
关键字隐藏 属性。这从多态调度的角度来看是行不通的(Mvc 将 getter 称为 DisplayFormatAttribute
而不是 LocalizedDisplayFormatAttribute
,因此您的阴影 属性 永远不会被调用)
我试过 TypeDescriptor.Refresh()
重载 https://msdn.microsoft.com/en-us/library/z1ztz056(v=vs.110).aspx 但没有成功
我所知道的其余选项在某种程度上并不方便或不令人惊奇。可能不推荐。
- 有些方法可以成功刷新
AssociatedMetadataTypeTypeDescriptionProvider TypeDescriptors
。我对这些不太熟悉,所以完全可以有一个。我只是目前没有看到。
- 返工或创建您自己的
ModelMetadataProvider
。一切都是开源的,所以它是可能的,但我不确定我是否会推荐它,除非作为最后的手段。
- 您可以使用 TypeDescriptor api 来强制重新实例化您的属性,无论何时它被拉出。参见 。
- 直接在 MVC 中为所需的属性建模(作为模型属性,而不是属性)。可以是全新的属性,或者你可以在你的原始属性中有某种逻辑,当 null return 其他东西时。虽然处理起来很尴尬。
没什么了不起的,我知道。也许这会给其他人足够的洞察力来想出更好的东西?
要自行验证,请参阅
https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DataAnnotationsModelMetadataProvider.cs CreateMetaData
方法调用 SetFromDataTypeAndDisplayAttributes
方法设置 result.NullDisplayText = displayFormatAttribute.NullDisplayText;
DataAnnotationsModelMetadataProvider
extends AssociatedMetadataProvider
负责传递属性。以 https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/AssociatedMetadataProvider.cs GetMetadataForProperty
方法为例。
我通过以下代码在资源的 DisplayFormat 中设置 NullDisplayText
public class LocalizedDisplayFormatAttribute : DisplayFormatAttribute
{
private readonly PropertyInfo _propertyInfo;
public LocalizedDisplayFormatAttribute(string resourceKey, Type resourceType)
: base()
{
this._propertyInfo = resourceType.GetProperty(resourceKey, BindingFlags.Static | BindingFlags.Public);
if (this._propertyInfo == null)
{
return;
}
base.NullDisplayText = (string)this._propertyInfo.GetValue(this._propertyInfo.DeclaringType, null);
}
public new string NullDisplayText
{
get
{
return base.NullDisplayText;
}
set
{
base.NullDisplayText = value;
}
}
}
我使用的默认区域性是 "en-US",一旦我将区域性更改为 es-AR 并加载页面,它就可以正常工作,但是当我将区域性更改回 en-US 时,字段不会转换回来.
我通过以下方式改变文化
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
try
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
CultureInfo ci = new CultureInfo(culutureCode);
System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
System.Threading.Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(ci.Name);
}
catch
{
}
}
我在 ViewModel 中使用 DisplayFormat 属性作为
public class AlarmCodeDetailsViewModel
{
/// <summary>
/// Gets or sets the alarm code ID
/// </summary>
public int AlarmCodeID { get; set; }
/// <summary>
/// Gets or sets the alarm code
/// </summary>
[LocalizedDisplayName("Label_AlarmCode")]
[LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)]
public string Code { get; set; }
/// <summary>
/// Gets or sets the Description
/// </summary>
[LocalizedDisplayName("Label_Description")]
[LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)]
public string Description { get; set; }
/// <summary>
/// Gets or sets the Notes
/// </summary>
[LocalizedDisplayName("Label_Notes")]
[LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)]
public string Notes { get; set; }
}
这里有一些问题的见解。
Mvc 使用一种类型描述符 (AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type)
) 来读取模型的属性。 TypeDescriptors 缓存有关特性和特性的信息。因此,就 TypeDescriptor api 而言,您的 LocalizedDisplayFormatAttribute
属性仅被实例化一次,这意味着资源信息仅被读取一次(在构造时)。请参阅答案的底部以供参考。
无效的解决方案
眨眼反应是每次通过getter访问时,只从您的
LocalizedDisplayFormatAttribute NullDisplayText
中提取最新的资源信息。不幸的是DisplayFormatAttribute
NullDisplayText
不是虚拟的,您正在用new
关键字隐藏 属性。这从多态调度的角度来看是行不通的(Mvc 将 getter 称为DisplayFormatAttribute
而不是LocalizedDisplayFormatAttribute
,因此您的阴影 属性 永远不会被调用)我试过
TypeDescriptor.Refresh()
重载 https://msdn.microsoft.com/en-us/library/z1ztz056(v=vs.110).aspx 但没有成功
我所知道的其余选项在某种程度上并不方便或不令人惊奇。可能不推荐。
- 有些方法可以成功刷新
AssociatedMetadataTypeTypeDescriptionProvider TypeDescriptors
。我对这些不太熟悉,所以完全可以有一个。我只是目前没有看到。 - 返工或创建您自己的
ModelMetadataProvider
。一切都是开源的,所以它是可能的,但我不确定我是否会推荐它,除非作为最后的手段。 - 您可以使用 TypeDescriptor api 来强制重新实例化您的属性,无论何时它被拉出。参见 。
- 直接在 MVC 中为所需的属性建模(作为模型属性,而不是属性)。可以是全新的属性,或者你可以在你的原始属性中有某种逻辑,当 null return 其他东西时。虽然处理起来很尴尬。
没什么了不起的,我知道。也许这会给其他人足够的洞察力来想出更好的东西?
要自行验证,请参阅
https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DataAnnotationsModelMetadataProvider.cs CreateMetaData
方法调用 SetFromDataTypeAndDisplayAttributes
方法设置 result.NullDisplayText = displayFormatAttribute.NullDisplayText;
DataAnnotationsModelMetadataProvider
extends AssociatedMetadataProvider
负责传递属性。以 https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/AssociatedMetadataProvider.cs GetMetadataForProperty
方法为例。