2015-08-15 59 views
3

我正在尋找一種方法來查找具有某個屬性的所有屬性。這不僅需要在單個類上工作,而且需要在內部遞歸地工作。在下面的例子中(有效的),我有一個遞歸的方法能夠做到這一點,但我不確定這是否是最有效的方法。使用反射的深度掃描 - 有更好的方法嗎?

在這種情況下,我正在尋找具有[Localizable]屬性的字符串屬性,並用本地化文本替換字符串。

任何意見,以改善本地化的方法或實際上整體的方法表示讚賞。提前致謝!

public class C1 
{ 
    [Localizable] 
    public string L1 { get; set; } 

    public C2[] C2Array { get; set; } 
} 

public class C2 
{ 
    [Localizable] 
    public string L2 { get; set; }  

    public C3 C3 { get; set; } 

    public List<C3> C3List { get; set; } 
} 

public class C3 
{ 
    [Localizable] 
    public string L3 { get; set; } 
}  

public static void Localize(object o, string cultureInfo) 
{ 
    var t = o.GetType(); 
    if (t.IsPrimitive || t == typeof(string)) 
    { 
     return; 
    } 

    foreach (var property in t.GetProperties(BindingFlags.Public | BindingFlags.Instance)) 
    { 
     var pt = property.PropertyType; 
     if (pt == typeof(string)) 
     { 
      if (!Attribute.IsDefined(property, typeof(LocalizableAttribute))) 
      { 
       continue; 
      } 
      var localizedText = GetLocalizedText(property.GetValue(o, null).ToString(), cultureInfo); 
      property.SetValue(o, localizedText, null); 
      continue; 
     } 

     var value = property.GetValue(o, null); 
     if (value == null) 
     { 
      continue; 
     } 

     if (pt.IsArray) 
     { 
      foreach (var el in (object[])value) 
      { 
       Localize(el, cultureInfo); 
      } 
     } 
     else if (pt.IsGenericType && pt.GetGenericTypeDefinition() == typeof(List<>)) 
     { 
      foreach (var el in (IEnumerable)value) 
      { 
       Localize(el, cultureInfo); 
      } 
     } 
     else if (pt.IsClass) 
     { 
      Localize(value, cultureInfo); 
     } 
    } 
} 
+0

代碼中的「value」是什麼,它來自哪裏? – pasty

+0

對不起我的錯誤,(壞的複製和粘貼!)。更正 – David

+0

現在「響應」丟失。 – pasty

回答

1

您的代碼工作正常。它可以變得更簡潔,但你仍然需要邏輯,你已經實現:

public static void Localize(object o, string cultureInfo) 
{ 
    if (o != null) 
    { 
     foreach (var property in o.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) 
     { 
      if (property.CustomAttributes.FirstOrDefault(ca => ca.AttributeType == typeof(LocalizableAttribute)) != null) 
      { 
       property.SetValue(o, GetLocalizedText(property.GetValue(o, null).ToString(), cultureInfo), null); 
      } 
      else 
      { 
       var value = property.GetValue(o); 
       if (value != null) 
       { 
        if (property.PropertyType.IsArray || (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(List<>))) 
        { 
         foreach (var el in (IEnumerable)value) 
         { 
          Localize(el, cultureInfo); 
         } 
        } 
        else 
        { 
         Localize(value, cultureInfo); 
        } 
       } 
      } 
     } 
    } 
} 

以下示例代碼輸入使用重構方法(忽略.Dump()方法 - 這是一個LINQPad extension):

var c1 = new C1() { L1 = "L1" }; 
c1.C2Array = new C2[10]; 
c1.C2Array[0] = new C2() { L2 = "L2", C3 = new C3 { L3 = "L3" }, C3List = new List<C3> { new C3 { L3 = "ListL3" } } }; 
Localize(c1, "DE"); 
c1.Dump(); 

的輸出是一樣的,從您的實現:

enter image description here

至於是否有更好的方法來定位字符串 - 這取決於您的需求和條件(並且您沒有顯示GetLocalizedText方法的實現 - 我只能做出假設)。如果您有WPF或Windows窗體甚至控制檯應用程序,那麼使用resource files更容易理解和實現string translation(並且不需要反射)。

+3

如果有兩個類之間的循環依賴關係,這將陷入無限循環,最好也檢查以及 –