今天我遇到了同样的问题,因为我试图让具有实体框架和验证属性的 wpf 应用程序实现全球化。
我尝试了不同的解决方案,目前,我最终CustomResourceManager
根据 Dave Sexton 在这篇文章中描述的示例创建了该解决方案:http ://www.pcreview.co.uk/forums/load-resources-string-table-database- t2892227.html
基本上我已经实现了我的DatabaseResourceManager
和DatabaseResourceSet
派生的ResourceManager
,ResourceSet
分别是这样的:
DatabaseResourceManager
实施:
public class DatabaseResourceManager : ResourceManager
{
#region Singleton pattern http://msdn.microsoft.com/en-us/library/ff650316.aspx
private static volatile DatabaseResourceManager instance;
private static object syncRoot = new Object();
private DatabaseResourceManager() : base() { }
public static DatabaseResourceManager Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new DatabaseResourceManager();
}
}
return instance;
}
}
#endregion
protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{
if (culture == null)
culture = CultureInfo.InvariantCulture;
return new DatabaseResourceSet(culture);
}
}
和DatabaseResourceSet
实施:
public class DatabaseResourceSet : ResourceSet
{
private readonly CultureInfo culture;
private static readonly Dictionary<string, Hashtable> cachedResources = new Dictionary<string, Hashtable>();
public DatabaseResourceSet(CultureInfo culture)
{
if (culture == null)
throw new ArgumentNullException("culture");
this.culture = culture;
ReadResources();
}
protected override void ReadResources()
{
if (cachedResources.ContainsKey(culture.Name))
// retrieve cached resource set
{
Table = cachedResources[culture.Name];
return;
}
using (MyDatabaseContext db = new MyDatabaseContext())
{
var translations = from t in db.Translations
where t.CultureIso == culture.Name
select t;
foreach (var translation in translations)
{
Table.Add(translation.Chave, translation.Valor);
}
}
cachedResources[culture.Name] = Table;
}
}
由于我的 DataBaseResourceManager 实现了单调模式,因此我可以轻松访问它并获取如下数据:
public class LocalizedRequiredAttribute : RequiredAttribute
{
public LocalizedRequiredAttribute() : base()
{
}
public override string FormatErrorMessage(string name)
{
string localErrorMessage = DatabaseResourceManager.Instance.GetString(this.ErrorMessageResourceName) ?? ErrorMessage ?? "{0} is required"; //probably DataAnnotationsResources.RequiredAttribute_ValidationError would is a better option
return string.Format(System.Globalization.CultureInfo.CurrentCulture, localErrorMessage, new object[] { name });
}
}
现在的缺点:
就像 pcreview 帖子中所说的那样,winforms 不接受 this DataBaseResourceManager
,但在我的情况下,因为我使用的是 wpf,所以我没有这个问题(但由于ResourceManager
和 a的重复而出现了另一个小的内存问题DictionaryResource
)。不知道您是否可以在 winforms 中注入资源管理器,但这超出了您的问题。您已经知道的另一个缺点是我们必须派生 all ValidationAttribute
used 以便FormatErrorMessage
使用 。StringLengthAttribute
, RequiredAttribute
, RegularExpressionAttribute
, 等等。这很容易出错和笨拙。不幸的是,微软在这里并没有给我们太多空间。
希望我有所帮助,也许我将来会回顾这个答案来分享我对此的发现。
问候