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 然后我得到相应的语言字段
答案 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并且从此过上幸福的生活。