如何在不使用SharedResources的情况下本地化类库中的枚举?
我的应用包含MyApp.Web和MyApp.ClassLibrary两个项目,目前已通过标准SharedResources配置实现了类库中AccountType枚举的本地化,但希望为ClassLibrary项目配置独立的资源文件,不再依赖SharedResources。
遇到的错误提示:
InvalidOperationException: Cannot retrieve property 'Name' because localization failed. Type 'MyApp.ClassLibrary.AccountResources' is not public or does not contain a public static string property with the name 'Active'.
AccountType枚举代码:
namespace MyApp.ClassLibrary.Accounts; public enum AccountType { [Display(Name = "Active", ResourceType = typeof(AccountResources))] Active, [Display(Name = "Disabled", ResourceType = typeof(AccountResources))] Disabled, [Display(Name = "Demo", ResourceType = typeof(AccountResources))] Demo }
AccountResources类(ClassLibrary项目根目录):
namespace MyApp.ClassLibrary; public class AccountResources { }
资源文件配置尝试:
- 曾在Web项目的
Resources文件夹放置Accounts.AccountResources.uz-Latn-UZ.resx,访问修饰符设为「No code generation」(与SharedResources.resx设置一致) - 也曾尝试将资源文件移至ClassLibrary项目的
Resources文件夹,但错误依旧
Program.cs当前配置:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); builder.Services.AddControllersWithViews() .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) .AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResources)); });
注:当前使用SharedResources可正常本地化类库枚举,但希望改为独立资源文件实现。
1. 修正资源文件的命名与位置
资源文件的命名、位置必须与AccountResources类的命名空间严格匹配:
- 由于
AccountResources的命名空间是MyApp.ClassLibrary,资源文件需命名为MyApp.ClassLibrary.AccountResources.uz-Latn-UZ.resx - 将资源文件放在ClassLibrary项目的
Resources文件夹下(无此文件夹则新建) - 资源文件的「访问修饰符」需设置为「Public」(不能是No code generation,否则无法生成对应强类型属性供本地化调用)
2. 调整DataAnnotations本地化提供者配置
当前配置强制所有本地化都使用SharedResources,需修改为动态识别资源类型:
builder.Services.AddControllersWithViews() .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) .AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => { // 获取当前类型标注的ResourceType var displayAttr = type.GetCustomAttributes(typeof(DisplayAttribute), false) .Cast<DisplayAttribute>() .FirstOrDefault(); if (displayAttr?.ResourceType != null) { return factory.Create(displayAttr.ResourceType); } // 未指定ResourceType时,回退到SharedResources return factory.Create(typeof(SharedResources)); }; });
3. 完善资源文件内容
打开AccountResources.uz-Latn-UZ.resx,添加对应键值对(示例为乌兹别克语):
<data name="Active" xml:space="preserve"> <value>Faol</value> </data> <data name="Disabled" xml:space="preserve"> <value>Faol emas</value> </data> <data name="Demo" xml:space="preserve"> <value>Demo</value> </data>
4. 验证类的访问性
确保AccountResources类为public,且MyApp.ClassLibrary项目已被MyApp.Web项目正确引用。
内容的提问来源于stack exchange,提问作者Donny

