2009-09-23 60 views
0

Ø总是来自一个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)和我赶上与第一如果然后我得到了相应的语言领域

+0

你到底在做什么? – 2009-09-23 17:33:03

+0

看起来他根据配置的语言调用带“en”或“fr”前缀的方法。 – 2009-09-23 17:36:25

+0

它会返回法语(descfr字段)和英语(descen字段) – Fredou 2009-09-23 17:36:26

回答

0

不幸的是,运行时反射将需要除非你能将desc方法整合到每个对象中,可能通过s ome类实体基类或代码生成和部分类。

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

虽然这些都是实体类,但在我看来,好像模式更改可能更可取。而不是使用多个descFoo列,添加一个包含{entity PK,language,text}的表。

1

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

您的描述字段只能包含DescriptionId,您可以通过额外提供语言标识在Descriptions表中查找此标识。

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(); 
+0

这是我现在有这个问题是在应用程序内部,哪个字段选择 – Fredou 2009-09-23 18:07:16

+0

模式修订是更好的方式去,但如果你嫁给了双语言在1表格方法,那么为什么不只是有一个“如果(var.Sess.lang = Sess.elang.en)然后返回tableCountry.descen否则返回tableCountry.descfr结束如果”。道歉,如果代码是穷人,很长一段时间,因为我冒险进入VB。 – Lazarus 2009-09-23 18:16:27

+0

@Lazarus,我的模式为每个领域都有专门的表格,可以是法语或英语,所以我已经对这个部分很满意,阅读我的问题的结尾,看看实际问题,代码不是一个好的选择,不要忘记,我需要检查对象是否为空,如果不是,那么我可以决定我要采用哪个字段。 – Fredou 2009-09-23 18:22:32

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,快乐地生活。

+0

这个类来自一个linq2sql对象,所以我不能修改它 – Fredou 2009-09-23 19:13:47

+0

你可以通过使用部分类来使用这种方法。我在我的答案中增加了细节。 – 2009-09-23 20:01:29

相关问题