从使用资源文件的 class 属性 获取本地化的显示名称属性
Get localized display name attribute from a class property which use a resource file
简介
我有一个 class,它的属性通过资源文件的数据注释进行了本地化,如下所示:
[Display(Name = nameof(ResxFile.SomeProperty), ResourceType = typeof(ResxFile)]
public string SomeProperty { get; set; }
其中 ResxFile
是一个 .resx 文件,我正在使用 Name = nameof(ResxFile.SomeProperty)
获取资源文件行的名称 属性(使其成为强类型),并且ResourceType = typeof(ResxFile)
表示使用哪个资源文件。
在我的 ResxFile
中,对于前面的例子,我会有这样的东西:
Name | Value
------------------------------------------
SomeProperty | Some property localized
并且通过这种方式,例如,我可以将我的 class 绑定到一个网格,列名将根据资源文件的内容进行本地化。
问题
我正在使用一种动态映射,我在其中使用 class 的 属性 名称,通常我会用这样的方式获取它们:string propertyName = typeof(MyClassName).GetProperty(myPropertyName).Name
在这种情况下,我需要的是根据资源文件分配给 属性 的本地化名称。更清楚地说:string localizedPropertyName = typeof(MyClassName).GetProperty(myPropertyName).SomeMagic();
其中 localizedPropertyName
将是“部分 属性 本地化”
我一直在寻找 CustomAttributes
,但我只能获得显示名称属性和某些类型,这使我从事另一项工作,即调用资源文件以获取 a 的值名字.
我正在使用 .Net Framework 4.7。
提前致谢!
希望这对您有所帮助,因为我过去曾使用这种方法来翻译数据库中的键。这不包括从资源文件中提取数据,但您可以在 属性 上声明 [Display]
属性并使用全名作为键,或者提供一个静态字符串作为键以备后用在元数据提供者中。
添加您自己的元数据提供商
public class MyMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,
Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
var metadata = new ModelMetadata(this, containerType, modelAccessor, modelType, propertyName);
//Do what ever you want here to translate either by the property name or the display attribute key
if (propertyName != null)
{
var displayAttribute = attributes.OfType<DisplayAttribute>().FirstOrDefault();
if (displayAttribute != null)
{
//Translate using the key you provided before however you like
metadata.DisplayName = TranslateFunction(displayAttribute.Name);
}
}
return metadata;
}
}
将翻译键添加到道具中
[Display(Name = "ResourceKey")]
public string Something { get; set; }
将此添加到应用程序启动
protected void Application_Start(object sender, EventArgs e)
{
ModelMetadataProviders.Current = new MyMetadataProvider();
}
最后,我自己找到了解决办法。
问题
然后,明确上下文,我们得到的只是一个class
(从中我们可以提取它的类型)和一个字符串上的PropertyName
,我们想要的是class 的 属性 的本地化 DisplayName
,根据装饰上分配的 Resource File
。
让我们假设一些元素开始。我们有 class MyClass
,它有一个名为 MyProperty
的 属性,它将与资源文件一起本地化 MyResx
:
public class MyClass
{
private string myProperty;
[Display(Name = nameof(MyResx.MyProperty), ResourceType = typeof(MyResx))]
public string MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
}
资源文件 MyResx
,有一些本地化的名称字符串 MyProperty
,看起来像这样:
解决方法
// We start with the class type, and the property name on a string
Type classType = typeof(MyClass);
string nameOfTheProperty = "MyProperty";
/* Now we get the MemberInfo of our property, wich allow us to get the
* property metadata, where is the information we are looking for. */
MemberInfo propertyMetadata = classType.GetProperty(nameOfTheProperty);
/* The decorations we used, are "Custom Attributes". Now we get those
* attributes from our property metadata: */
var customAttributes = CustomAttributeData.GetCustomAttributes(propertyMetadata).FirstOrDefault();
/* If we pay attention to our decoration, we defined "Name = nameof(MyResx.MyProperty)"
* and "ResourceType = typeof(MyResx))", so, what we are looking for from our custom
* attribures are those members, Name and ResourceType: */
var customAttributeName = customAttributes.NamedArguments.FirstOrDefault(n => n.MemberName == "Name");
var name = (customAttributeName != null) ? (string)customAttributeName.TypedValue.Value : null;
var customAttributeResourceType = customAttributes.NamedArguments.FirstOrDefault(n => n.MemberName == "ResourceType");
var resourceType = (customAttributeResourceType != null) ? (Type)customAttributeResourceType.TypedValue.Value : null;
/* Now, having the resource file from the decoration, we just create an instance to
* use it: */
var decorationResx = new ComponentResourceManager(resourceType);
// And finally, from our resource file, we get our localized display name
string localizedAttribute = decorationResx.GetString(name);
额外
我从 Microsoft 参考资料中获得了很多关于 NamedArguments 的重要信息,此处:https://docs.microsoft.com/en-us/dotnet/api/system.reflection.customattributedata.namedarguments?view=netcore-3.1
简介
我有一个 class,它的属性通过资源文件的数据注释进行了本地化,如下所示:
[Display(Name = nameof(ResxFile.SomeProperty), ResourceType = typeof(ResxFile)]
public string SomeProperty { get; set; }
其中 ResxFile
是一个 .resx 文件,我正在使用 Name = nameof(ResxFile.SomeProperty)
获取资源文件行的名称 属性(使其成为强类型),并且ResourceType = typeof(ResxFile)
表示使用哪个资源文件。
在我的 ResxFile
中,对于前面的例子,我会有这样的东西:
Name | Value
------------------------------------------
SomeProperty | Some property localized
并且通过这种方式,例如,我可以将我的 class 绑定到一个网格,列名将根据资源文件的内容进行本地化。
问题
我正在使用一种动态映射,我在其中使用 class 的 属性 名称,通常我会用这样的方式获取它们:string propertyName = typeof(MyClassName).GetProperty(myPropertyName).Name
在这种情况下,我需要的是根据资源文件分配给 属性 的本地化名称。更清楚地说:string localizedPropertyName = typeof(MyClassName).GetProperty(myPropertyName).SomeMagic();
其中 localizedPropertyName
将是“部分 属性 本地化”
我一直在寻找 CustomAttributes
,但我只能获得显示名称属性和某些类型,这使我从事另一项工作,即调用资源文件以获取 a 的值名字.
我正在使用 .Net Framework 4.7。
提前致谢!
希望这对您有所帮助,因为我过去曾使用这种方法来翻译数据库中的键。这不包括从资源文件中提取数据,但您可以在 属性 上声明 [Display]
属性并使用全名作为键,或者提供一个静态字符串作为键以备后用在元数据提供者中。
添加您自己的元数据提供商
public class MyMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes,
Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
var metadata = new ModelMetadata(this, containerType, modelAccessor, modelType, propertyName);
//Do what ever you want here to translate either by the property name or the display attribute key
if (propertyName != null)
{
var displayAttribute = attributes.OfType<DisplayAttribute>().FirstOrDefault();
if (displayAttribute != null)
{
//Translate using the key you provided before however you like
metadata.DisplayName = TranslateFunction(displayAttribute.Name);
}
}
return metadata;
}
}
将翻译键添加到道具中
[Display(Name = "ResourceKey")]
public string Something { get; set; }
将此添加到应用程序启动
protected void Application_Start(object sender, EventArgs e)
{
ModelMetadataProviders.Current = new MyMetadataProvider();
}
最后,我自己找到了解决办法。
问题
然后,明确上下文,我们得到的只是一个class
(从中我们可以提取它的类型)和一个字符串上的PropertyName
,我们想要的是class 的 属性 的本地化 DisplayName
,根据装饰上分配的 Resource File
。
让我们假设一些元素开始。我们有 class MyClass
,它有一个名为 MyProperty
的 属性,它将与资源文件一起本地化 MyResx
:
public class MyClass
{
private string myProperty;
[Display(Name = nameof(MyResx.MyProperty), ResourceType = typeof(MyResx))]
public string MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
}
资源文件 MyResx
,有一些本地化的名称字符串 MyProperty
,看起来像这样:
解决方法
// We start with the class type, and the property name on a string
Type classType = typeof(MyClass);
string nameOfTheProperty = "MyProperty";
/* Now we get the MemberInfo of our property, wich allow us to get the
* property metadata, where is the information we are looking for. */
MemberInfo propertyMetadata = classType.GetProperty(nameOfTheProperty);
/* The decorations we used, are "Custom Attributes". Now we get those
* attributes from our property metadata: */
var customAttributes = CustomAttributeData.GetCustomAttributes(propertyMetadata).FirstOrDefault();
/* If we pay attention to our decoration, we defined "Name = nameof(MyResx.MyProperty)"
* and "ResourceType = typeof(MyResx))", so, what we are looking for from our custom
* attribures are those members, Name and ResourceType: */
var customAttributeName = customAttributes.NamedArguments.FirstOrDefault(n => n.MemberName == "Name");
var name = (customAttributeName != null) ? (string)customAttributeName.TypedValue.Value : null;
var customAttributeResourceType = customAttributes.NamedArguments.FirstOrDefault(n => n.MemberName == "ResourceType");
var resourceType = (customAttributeResourceType != null) ? (Type)customAttributeResourceType.TypedValue.Value : null;
/* Now, having the resource file from the decoration, we just create an instance to
* use it: */
var decorationResx = new ComponentResourceManager(resourceType);
// And finally, from our resource file, we get our localized display name
string localizedAttribute = decorationResx.GetString(name);
额外
我从 Microsoft 参考资料中获得了很多关于 NamedArguments 的重要信息,此处:https://docs.microsoft.com/en-us/dotnet/api/system.reflection.customattributedata.namedarguments?view=netcore-3.1