我们有一个将用户界面翻译成多种语言的类。这个类的基本思想是它只是检查表单上的所有控件,并从xml文件中读取每个控件的文本值。
foreach(Control control in form.Controls)
{
if (control is Label)
ReadTextForLabel(control);
else if (control is MySuperCoolLabel)
ReadTextForMySuperCoolLabel(control);
...
}
因此,我们尝试创建一个通用类来翻译程序中的每个控件。
前一段时间我们遇到了一个问题,即我们有太多的类,比如来自不同库的MySuperCoolLabel。如果我们想要使用我们的翻译类在新程序中翻译界面,我们必须使用我们的SuperCoolLabels添加所有这些dll,即使程序中没有任何SuperCoolLabels。
问题是:如何避免所有这些依赖关系并仍然有一个通用类来翻译程序?
答案 0 :(得分:2)
也许您可以尝试区分不是按类型控制,而是将类型名称区分为字符串。类似的东西;
if (control.GetType().ToString() == "Label")
ReadTextForLabel(control);
else if (control.GetType().ToString() == "MySuperCoolLabel")
ReadTextForMySuperCoolLabel(control);
另一方面,我想知道为什么你没有使用.Net内置支持多语言。
答案 1 :(得分:1)
嗯,依赖关系是程序架构的完美之处。 要明确:
我假设您编写ReadTextForMySuperCoolLabel(..)
因为您需要将某些特定内容转换为 控件属性,这些属性不会遇到您使用的其他控件。
如果这是真的,就没有办法避免你所说的依赖。使用直接分配,使用反射,使用其他东西......必须有某人,某处说: “这是一个MySuperControl,所以这个,这是另一个,所以那个”。
如果有一种方法可以概括属性赋值。例如,您的应用中的所有控件都具有Text
属性。在这种情况下,可以使这些东西变得通用。
答案 2 :(得分:0)
好吧,一种方法是通过使用依赖注入框架(如Castle Windsor)来延迟绑定所有类,或者通过创建类似这样的类来滚动自己的类:
var myCoolClass = Activator.CreateInstance( typeof( MySuperCoolTextBox ) )
这样您就不需要添加对SuperCool库的引用,只需将它包含在您的binry中。但是,我猜测SuperCool控件是在表单设计器中使用的,因此您可能无法像这样设置控件。
答案 3 :(得分:0)
您的问题实际上违反了Liskovs替换原则,因为您的翻译类必须单独处理每个派生类型。
我们知道winforms必须具有控件类型:容器和控件。容器包含多个控件,而控件只是一个控件;)
我们可以使用该知识来创建通用表单翻译器:
public class UniversalFormTranslater
{
public void TranslateForm(System.Windows.Forms.ContainerControl container)
{
var name = container.Name;
var originalText = container.Text;
if (!string.IsNullOrEmpty(originalText))
container.Text = Translate(name);
TranslateControl(name, container);
}
private void TranslateControl(string parentName, System.Windows.Forms.ContainerControl control)
{
var name = parentName + "." + control.Name;
var originalText = control.Text;
if (!string.IsNullOrEmpty(originalText))
control.Text = Translate(name);
}
private void TranslateControl(string parentName, System.Windows.Forms.ContainerControl container)
{
var name = parentName + "." + container.Name;
var originalText = container.Text;
if (!string.IsNullOrEmpty(originalText))
container.Text = Translate(name);
foreach (var control in container.Controls)
{
TranslateControl(name, control);
}
}
public void Translate(string controlName)
{
// return the translation.
}
}
它寻找像:
这样的字符串使用以下方式翻译:
var translator = new UniversalFormTranslater();
translator.TranslateForm(form1);