2009-09-23 19 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

相關問題