65.9K
CodeProject 正在变化。 阅读更多。
Home

为对象的国际化添加支持

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (27投票s)

2011年12月21日

CPOL

2分钟阅读

viewsIcon

40788

downloadIcon

551

使用从数据源获取的本地化数据是一个问题。 这是一个很好的解决方案。

引言

在当今世界,本地化已成为我们开发应用程序中的必备要求。 我们可以通过对静态资源(如异常消息、标签文本等)使用资源文件轻松实现此目标。 但是,使用从数据源获取的本地化数据将是一个问题。 由于数据是动态的,因此无法使用资源文件解决此问题。

使用代码

大多数开发人员通过使用如下设计来解决此问题。

1000002697_1.jpg

如果我们看一下这个设计,我们可以看到我们正在为包含多语言数据的每个属性创建一个新对象。 所有这些对象导致开发人员编写更多代码,并且还会使应用程序代码更难以管理。 如果开发人员正在使用 ORM 工具,他/她最终会创建很多映射。

现在让我们从另一个角度思考,并尝试实现如下设计。

1000002697_2.jpg

如您所见,此设计更容易理解,并且具有很高的可重用性。 您可以使用 MultilanguageProperty 将多语言数据存储为对象的属性。

现在让我们看看如何从设计中编写这段代码。

首先,让我们编写将在 MultilanguageProperty 中使用的 Language 类。

public class Language
{
    public enum ApplicationLanguage
    {
        Turkish,
        English,
    }
    public static ApplicationLanguage GetDefaultLanguage()
    {
        return ApplicationLanguage.Turkish;
    }
}

如您所见,我们在枚举中定义了要使用的语言。 并且我们实现了一个负责返回默认语言的方法。 此方法可以根据我们的实现返回每个会话或每个用户的默认语言。

让我们开始编写 MultilanguageProperty 对象。

public class MultilanguageProperty<T>:IEnumerable<KeyValuePair<Language.ApplicationLanguage,T>>
{
    public IDictionary<Language.ApplicationLanguage, T> Values { get; set; }
    public MultilanguageProperty()
    {
        Values = new Dictionary<Language.ApplicationLanguage, T>();
    }

首先,为了将我们的对象与任何类型一起使用,我们将对象设为泛型。 为了允许用户迭代此对象中的子项,我们如上所述实现了 IEnumerable 接口。

声明类型为 IDictionary 的属性是此实现的主要思想。 此 Dictionary 将根据语言值存储数据。 如您所见,IDictinary 是一种泛型类型,以 ApplicationLanguage 枚举作为键,以 T 泛型类型作为值。 并在我们代码的构造函数中,我们创建此 Dictionary 的实例。

现在让我们实现一些代码来访问存储在 Values 属性中的数据。

        public T GetValue(Language.ApplicationLanguage language)
        {
            return (T)Values[language];
        }
        public T GetValue()
        {
            Language.ApplicationLanguage applicationLanguage = Language.GetDefaultLanguage();
            return (T)Values[applicationLanguage];
        }
        public T this[Language.ApplicationLanguage l]
        {
            get
            {
                return Values[l];
            }
            set
            {
                Values[l] = value;
            }
        }
        public static implicit operator T(MultilanguageProperty<T> instance)
        {
            if (instance == null)
            {
                return default(T);
            }
            return instance.GetValue();
        }
        public static implicit operator 
          List<KeyValuePair<Language.ApplicationLanguage,T>>(MultilanguageProperty<T> instance)
        {
            if (instance == null)
            {
                return null;
            }
            return instance.Values.ToList();
        }
        #region IEnumerable<KeyValuePair<ApplicationLanguage,T>> Members
 
        public IEnumerator<KeyValuePair<Language.ApplicationLanguage, T>> GetEnumerator()
        {
            return Values.GetEnumerator();
        }
 
        #endregion
 
        #region IEnumerable Members
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return Values.GetEnumerator();
        }
 
        #endregion
    }
}

如您所见,开发了 GetValue 方法的两个重载。 其中一个返回默认语言的值,另一个返回作为参数传递的语言的值。

此外,还有一个索引器属性,可以通过索引器访问值。 并且定义了一个隐式运算符,无需使用任何强制转换或转换函数即可访问默认语言值。

现在让我们创建一个测试应用程序。

public class TestObject
{
    public TestObject()
    {
        this.Name = new MultilanguageProperty<string>();
    }
    public int Id { get; set; }
    public string UniversalCode { get; set; }
    public MultilanguageProperty<string> Name { get; set; }
}
class Program
{
    public static List<TestObject> GetSampleDataForTestObject()
    {
        List<TestObject> listTestObject = new List<TestObject>();

        TestObject testObject1 = new TestObject { Id = 1, UniversalCode = "TR" };
        testObject1.Name.Values.Add(Language.ApplicationLanguage.Turkish, "Türkiye");
        testObject1.Name.Values.Add(Language.ApplicationLanguage.English, "Turkey");

        TestObject testObject2 = new TestObject { Id = 2, UniversalCode = "USA" };
        testObject2.Name.Values.Add(Language.ApplicationLanguage.Turkish, "Amerika Birleşik Devletleri");
        testObject2.Name.Values.Add(Language.ApplicationLanguage.English, "United States Of America");

        TestObject testObject3 = new TestObject { Id = 3, UniversalCode = "FR" };
        testObject3.Name.Values.Add(Language.ApplicationLanguage.Turkish, "Fransa");
        testObject3.Name.Values.Add(Language.ApplicationLanguage.English, "France");

        listTestObject.Add(testObject1);
        listTestObject.Add(testObject2);
        listTestObject.Add(testObject3);

        return listTestObject;
    }
    static void Main(string[] args)
    {

        List<TestObject> listTestObject = GetSampleDataForTestObject();
        WriteAllList(listTestObject);
        Console.WriteLine();
        WriteForSpecificLanguageByIndexer(listTestObject);
        Console.WriteLine();
        WriteForSpecificLanguageByGetValue(listTestObject);
        Console.WriteLine();
        WriteForDefaultLanguageByIndexer(listTestObject);
        Console.WriteLine();
        WriteForDefaultLanguageByGetValue(listTestObject);
        Console.WriteLine();
        WriteForDefaultLanguageByImplicit(listTestObject);
        Console.Read();
    }
    private static void WriteAllList(List<TestObject> listTestObject)
    {
        Console.WriteLine("Writing All List");
        foreach (TestObject to in listTestObject)
        {
            Console.WriteLine("Id:" + to.Id + " Code:" + to.UniversalCode);
            foreach (KeyValuePair<Language.ApplicationLanguage, string> kvp in to.Name)
            {
                Console.WriteLine("     Language:" + kvp.Key.ToString() + " Name:" + kvp.Value.ToString());
            }
        }
    }
    private static void WriteForSpecificLanguageByIndexer(List<TestObject> listTestObject)
    {
        Console.WriteLine("Writing Specific Language Value By Indexer");
        string s = listTestObject[0].Name[Language.ApplicationLanguage.English];
        Console.WriteLine(s);
    }
    private static void WriteForSpecificLanguageByGetValue(List<TestObject> listTestObject)
    {
        Console.WriteLine("Writing Specific Language Value By GetValue Method");
        string s = listTestObject[0].Name.GetValue(Language.ApplicationLanguage.English);
        Console.WriteLine(s);
    }
    private static void WriteForDefaultLanguageByIndexer(List<TestObject> listTestObject)
    {
        Console.WriteLine("Writing Default Language Value By Indexer");
        string s = listTestObject[1].Name[Language.GetDefaultLanguage()];
        Console.WriteLine(s);
    }
    private static void WriteForDefaultLanguageByGetValue(List<TestObject> listTestObject)
    {
        Console.WriteLine("Writing Default Language Value By GetValue Method");
        string s = listTestObject[1].Name.GetValue();
        Console.WriteLine(s);
    }
    private static void WriteForDefaultLanguageByImplicit(List<TestObject> listTestObject)
    {
        Console.WriteLine("Writing Default Language Value By Implicit Operator");
        string s = listTestObject[2].Name;
        Console.WriteLine(s);
    }

}

这是测试应用程序的输出。

1000002697_3.jpg

如有任何问题,请随时与我联系。

历史

  • 2011 年 12 月 22 日:初始版本。
© . All rights reserved.