我目前正在使用反射来做到这一点,有更好的方法吗?

时间:2009-09-23 17:30:25

标签: c# vb.net reflection

o 将始终来自entiryRef / TEntity(来自linq 2 sql)

我对c#或vb.net解决方案没问题(如果你不能,我会把它转换成vb.net)

Public Function desc(Of t)(ByRef o As t, Optional ByVal PropPrefix As String = "desc") As String
    If o Is Nothing Then
        Return ""
    Else
        Dim bind = Reflection.BindingFlags.Public Or Reflection.BindingFlags.IgnoreCase Or Reflection.BindingFlags.Instance
        Dim _desc = PropPrefix & If(var.Sess.lang = Sess.elang.en, PropPrefix & "en", "fr")
        Dim pinfo As Reflection.PropertyInfo = o.GetType.GetProperty(_desc, bind)

        Return pinfo.GetValue(o, Nothing).ToString
    End If
End Function

小背景

我有一个像这样的数据库

tableUser
-----------------
id
name
countryid

tableCountry
--------
countryid
descEn
descFr

当我显示有关用户的信息时,我想轻松地显示在应用程序中选择的优秀语言

那个例子,我有更多的表和更多的查找表

使用 linq 2 sql 如果数据库中的字段为空,则该对象将为“无”(null)并且我正在捕获第一个 if 然后我得到相应的语言字段

3 个答案:

答案 0 :(得分:1)

使用您当前的设计,您无法做得更好。相反,您应该考虑进行重大的重新设计,并从专用表中获取本地化值,而不是使用所有语言的列。

您的说明字段只能包含DescriptionId,您可以通过另外提供语言标识符在Descriptions表中查看此ID。

DescriptionId | Language | Description
--------------------------------------
            1 | fr       | French Foo
            1 | en       | English Foo
            2 | fr       | French Bar
            2 | fr       | English Bar

这很容易让以后添加其他语言。如果您不希望使用其他语言,可以使用以下语言。

DescriptionId | English     | French
----------------------------------------
            1 | English Foo | French Foo
            2 | English Bar | French Bar

只是为了澄清 - 我不建议为每个实体或列引入一个本地化表,而是为所有实体和列引入一个。因此,包含可本地化信息的所有列都将成为同一个表的外键。因此,可以集中获取本地化字符串的代码,而不是为每个实体重新创建它。

我有与papper1337相同的想法,但没有提出它,因为我相信重新设计数据库是要走的路。我会建议如下。

创建界面ILocalizedEntity

public interface ILocalizedEntity
{
    String descEn { get; }
    String descFr { get; }
}

将此界面添加到所有本地化实体。这可以很容易地完成,因为LINQ to SQL创建了部分类。在C#中,我将创建一个新文件Country.cs并添加以下代码。

public partial class Country : ILocalizedEntity
{
}

该接口由LINQ to SQL生成的代码实现。

现在,您可以创建如下方法。

public static GetLocalizedDescription(this ILocalizedEntity entity)
{
    if (entity == null)
    {
        return String.Empty;
    }
    else
    {
        switch (Session.Language)
        {
            case Language.English:
                return entity.descrEn;
                break;

            case Language.French:
                return entity.descrFr;
                break;

            default:
                throw new InvalidOperationException();
        }
    }
}

这是一个C#扩展方法,您可以按如下方式使用它。

someEntity.GetLocalizedDescription();

答案 1 :(得分:0)

不幸的是,除非您可以通过某种实体基类或代码生成和部分类将desc方法集成到每个对象中,否则将需要运行时反射。

代码生成方法:对于每个实体类,如果它包含一个或多个descFoo属性,则生成一个desc属性,用于提取正确的属性。如果在编写CodeDom之前无法修改CodeDom,您还可以编译实体类,反映/内省结果,生成部分类,并使用添加的代码重新编译。

因为这些是实体类,所以在我看来好像架构更改可能更好。不要使用多个descFoo列,而是添加一个由{entity PK,language,text}组成的表。

答案 2 :(得分:0)

我同意DanielBrückner。

话虽这么说,另一种实现方式是使用这样的接口:

public interface IEnglish
{
 public string DescriptionEN { get; }
}

public interface IFrench
{
 public string DescriptionFR { get; }
}

public interface IMultilingual : IEnglish, IFrench { }

public void desc<T>(ref T o, string propPrefix) where T : IMultilingual
{
 return Sess.lang = Sess.elang.en ? o.DescriptionEN : o.DescriptionFR
}

然后,任何包含英语/法语属性的课程都会实现IMultilingual并且从此过上幸福的生活。