如何在c#中本地化属性描述?
我正在开设一个将被其他国家的一些人使用的课程。 我必须将每条消息本地化,警告ec以便他们能够理解我们的意思。 在许多情况下,我实现了我的目标。 但是像描述这些属性属性在屁股上是如此痛苦。
这就是我现在所拥有的:
[Category("Editable Values"), Description("Sets the minimum select...")] public Ampere Simin { get {...} set {...} }
和
[Category("Editable Values"), Description(Localisation.Simin)] // "Localisation" here is the internal resource file that i wrote for messages, warnings, exceptions and -unfortunately- descriptions public Ampere Simin { get {...} set {...} }
这就是我想要做的。 但是不可能以这种方式使用Localisations。 有关我可以使用的东西的任何建议而不是它吗?
子类:
[STAThread] static void Main() { // just some example code to show it working in winforms, but // anything using System.ComponentModel should see the change Application.EnableVisualStyles(); Application.Run(new Form {Controls = {new PropertyGrid {Dock = DockStyle.Fill, SelectedObject = new Foo()}}}); } class Foo { // assume the following literals are keys, for example to a RESX [LocalizedCategory("cat")] [LocalizedDescription("desc")] [LocalizedDisplayName("disp name")] public string Bar { get; set; } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Delegate | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter)] class LocalizedDescriptionAttribute : DescriptionAttribute { static string Localize(string key) { // TODO: lookup from resx, perhaps with cache etc return "Something for " + key; } public LocalizedDescriptionAttribute(string key) : base(Localize(key)) { } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event)] class LocalizedDisplayNameAttribute : DisplayNameAttribute { static string Localize(string key) { // TODO: lookup from resx, perhaps with cache etc return "Something for " + key; } public LocalizedDisplayNameAttribute(string key) : base(Localize(key)) { } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Delegate | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter)] class LocalizedCategoryAttribute : CategoryAttribute { public LocalizedCategoryAttribute(string key) : base(key) { } protected override string GetLocalizedString(string value) { // TODO: lookup from resx, perhaps with cache etc return "Something for " + value; } }
[Required(ErrorMessageResourceName = "LogOnModel_UserName_Required", ErrorMessageResourceType = typeof(Resources.Global))] [Display(Name = "LogOnModel_UserName_Required",resourceType = typeof(Resources.Global))] public string UserName { get; set; }
请参阅: http : //geekswithblogs.net/shaunxu/archive/2010/05/06/localization-in-asp.net-mvc-ndash-3-days-investigation-1-day.aspx
我们来看看这个示例类:
// ------------------------------------------------------------------------ public class Customer { // ---------------------------------------------------------------------- [Category( "Editable Values" ), LocDescription( "FirstName", "Sets the first name..." )] public string FirstName { get; set; } // ---------------------------------------------------------------------- [Category( "Editable Values" ), LocDescription( Key = "LastName", DefaultDescription = "Sets the last name..." )] public string LastName { get; set; } } // class Customer
现在您可以实现自定义属性类:
// ------------------------------------------------------------------------ public class LocDescriptionAttribute : DescriptionAttribute { // ---------------------------------------------------------------------- public LocDescriptionAttribute() { } // LocDescriptionAttribute // ---------------------------------------------------------------------- public LocDescriptionAttribute( string key, string defaultDescription ) : base( defaultDescription ) { Key = key; DefaultDescription = defaultDescription; } // LocDescriptionAttribute // ---------------------------------------------------------------------- public string Key { get; set; } // ---------------------------------------------------------------------- public string DefaultDescription { get; set; } // ---------------------------------------------------------------------- public override string Description { get { // load from resx string description = Strings.GetString( Key ); if ( string.IsNullOrEmpty( description ) ) { description = DefaultDescription; } return description; } } // Description } // class LocDescriptionAttribute
现在您有了本地化描述:
AttributeCollection attributes = TypeDescriptor.GetProperties( customer )[ "FirstName" ].Attributes; DescriptionAttribute myAttribute = (DescriptionAttribute)attributes[ typeof( DescriptionAttribute ) ]; ConsoleWiterLine( myAttribute.Description );
我结合了Marc Gravell和dsmith的答案:
首先:创建一个名为LocalizedDescriptionAttribute的Attribute类
public class LocalizedDescriptionAttribute : DescriptionAttribute { static string Localize(string key) { return YourResourceClassName.ResourceManager.GetString(key); } public LocalizedDescriptionAttribute(string key) : base(Localize(key)) { } }
将它用作LocalizedDescription(不需要“属性”一词)
public class Foo { // myString is a key that exists in your Resources file [LocalizedDescription("myString")] public string Bar { get; set; } }
Jani的回答略有扩展(对我来说效果很好):
string description = Strings.GetString( Key );
可以更清楚地完成
ResourceManager rm = YourResourceClassName.ResourceManager; string description = rm.GetString(Key);
这含糊不清,但不清楚原始代码中缺少什么。 资源类的.ResourceManager
属性是自动生成的。
然后,要访问它,请使用Glennular在此处描述的扩展方法: StackOverflow而不是字段/类名称中的硬编码(只使用LocDescriptionAttribute
而不是DescriptionAttribute
)。
我做的唯一其他调整是基于this IComparable enum
使其静态,以允许任何枚举使用它而不是锁定到特定类型; 鉴于我无法应用界面将其限制为我添加了描述的枚举,这是我能做的最好的事情。
似乎CategoryAttribute
具有基于内部资源查找本地化字符串的代码,但DescriptionAttribute
没有本地化。
来自Reflector:
public string Category { get { if (!this.localized) { this.localized = true; string localizedString = this.GetLocalizedString(this.categoryValue); if (localizedString != null) { this.categoryValue = localizedString; } } return this.categoryValue; } }
我想你会扩展属性并创建自己的实现,传递ResourceType。 像这样的东西,模糊地基于DataAnnotation
逻辑。 显然需要更多的清理。
public class LocaleDescriptionAttribute : DescriptionAttribute { ... public LocaleDescriptionAttribute(string resourceKey, Type resourceType) : base(resourceKey) { this.resourceType = resourceType; } public override string Description { get { var description = base.Description; PropertyInfo property = resourceType.GetProperty( description, BindingFlags.Public | BindingFlags.Static); if (property == null) { return description; } return property.GetValue(null, null) as string; } } }