Ces*_*Gon 5 multilingual domain-driven-design
我正在使用域驱动设计,我对我的域模型有一个非常清晰的描述.它包含120多个类,非常稳定.我们将在.NET 4和C#中实现它.问题是,我们需要模型多语言; 某些属性需要以多种语言存储.例如,Person类具有类型的Position属性,string该属性应该以英语(例如"Librarian")和西班牙语(例如"Bibliotecario")存储值.此属性的getter应根据某些语言参数返回英语或西班牙语版本.
在这里开始我的问题.我不知道如何参数化.我有两种主要方法可以做到:
string而是一个Dictionary<Language, string>,它可以让客户通过语言检索人的位置.选项1避免了全局状态,但它弄乱了我模型中几乎每个类的接口.另一方面,选项2的表达力较差,因为如果不查看全局设置,您无法分辨出将要获得的语言.此外,它还为全局设置中的每个类引入了依赖项.
请注意,我对数据库或ORM实现不感兴趣; 我只在域模型级别工作.
那我有两个具体的问题:
谢谢.
编辑.有人建议这是一个与用户界面相关的问题,因此可以通过.NET中的全球化/本地化支持来解决.我不同意.只有当您知道在编译时必须向用户显示的本地化文字时,UI本地化才有效,但这不是我们的情况.我的问题涉及在编译时未知的多语言数据,因为它将在运行时作为用户数据提供.这不是与UI相关的问题.
编辑2.请记住,Person.Position只是一个说明问题的玩具示例.它不是真实模型的一部分.不要试图批评或改进它; 这样做没有意义.我们的业务需求涉及许多无法编码为枚举类型或类似的属性,并且必须保留为自由文本.因此困难.
小智 5
鉴于以下内容:
一些用例涉及在所有支持的语言中设置对象的值; 其他人则涉及在一种给定语言中查看价值观.
我建议两种选择.这意味着Person和所有持有多语言内容的类应该将该内容保持在其状态,并且:
Position属性应以当前用户的语言设置/获取人员的位置 .
所有 语言设置/获取都应该有相应的属性或方法.
应该有一种方法来设置(甚至切换,如果需要)用户语言.我将使用抽象的SetLanguage(语言lang)方法和CurrentLanguage getter创建一个抽象类(例如BaseMultilingualEntity).您需要在某种类型的注册表中跟踪从BaseMultilingualEntity派生的所有对象,这些注册表将公开语言设置.
使用某些代码编辑
public enum Language {
English,
German
}
// all multilingual entity classes should derive from this one; this is practically a partly implemented observer
public abstract class BaseMultilingualEntity
{
public Language CurrentLanguage { get; private set; }
public void SetCurrentLanguage(Language lang)
{
this.CurrentLanguage = lang;
}
}
// this is practically an observable and perhaps SRP is not fully respected here but you got the point i think
public class UserSettings
{
private List<BaseMultilingualEntity> _multilingualEntities;
public void SetCurrentLanguage(Language lang)
{
if (_multilingualEntities == null)
return;
foreach (BaseMultilingualEntity multiLingualEntity in _multilingualEntities)
multiLingualEntity.SetCurrentLanguage(lang);
}
public void TrackMultilingualEntity(BaseMultilingualEntity multiLingualEntity)
{
if (_multilingualEntities == null)
_multilingualEntities = new List<BaseMultilingualEntity>();
_multilingualEntities.Add(multiLingualEntity);
}
}
// the Person entity class is a multilingual entity; the intention is to keep the XXXX with the XXXXInAllLanguages property in sync
public class Person : BaseMultilingualEntity
{
public string Position
{
set
{
_PositionInAllLanguages[this.CurrentLanguage] = value;
}
get
{
return _PositionInAllLanguages[this.CurrentLanguage];
}
}
private Dictionary<Language, string> _PositionInAllLanguages;
public Dictionary<Language, string> PositionInAllLanguages {
get
{
return _PositionInAllLanguages;
}
set
{
_PositionInAllLanguages = value;
}
}
}
public class Program
{
public static void Main()
{
UserSettings us = new UserSettings();
us.SetCurrentLanguage(Language.English);
Person person1 = new Person();
us.TrackMultilingualEntity(person1);
// use case: set position in all languages
person1.PositionInAllLanguages = new Dictionary<Language, string> {
{ Language.English, "Software Developer" },
{ Language.German, "Software Entwikcler" }
};
// use case: display a person's position in the user language
Console.WriteLine(person1.Position);
// use case: switch language
us.SetCurrentLanguage(Language.German);
Console.WriteLine(person1.Position);
// use case: set position in the current user's language
person1.Position = "Software Entwickler";
// use case: display a person's position in all languages
foreach (Language lang in person1.PositionInAllLanguages.Keys)
Console.WriteLine(person1.PositionInAllLanguages[lang]);
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)