2014-09-21 29 views
0

我有一個系統使用動態加載類型的動態運行時配置。BeanUtils到.NET的端口

系統正在加載基於XML和創建實例的類型。然後它從XML文件讀取「屬性」,在創建的實例上設置這些屬性。目前,它直接在實例上處理簡單屬性,但是,這些類型可以具有調用部分未知的設置層次結構。

我正在尋找類似於Java BeanUtils的utils-libraries [http://commons.apache.org/proper/commons-beanutils/]。我希望它能夠做這樣的事情(僞代碼):

Util.SetProperty(someInstance, "property1.property2, someValue); 

或許與擴展:

someInstance.SetProperty("property1.property2, someValue); 

而且隨着當然Get相反。

請注意,BeanUtils有它自己的風格來描述屬性,因此它適用於大多數類型的屬性,包括列表。

任何事情,或者對這個問題的不同建議?

回答

0

這是一個支持列表,字典和嵌套屬性的助手類,如果您需要支持多個索引器(非常罕見的情況),您應該擴展它。

public static class Helper 
{ 
    public static void SetProperty(object instance, string propery, object value) 
    { 
     const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 
     var properties = propery.Split('.'); 
     var type = instance.GetType(); 
     object[] index = null; 
     PropertyInfo property = null; 

     for (var i = 0; i < properties.Length; i++) 
     { 
      var indexValue = Regex.Match(properties[i], @"(?<=\[)(.*?)(?=\])").Value; 

      if (string.IsNullOrEmpty(indexValue)) 
      { 
       property = type.GetProperty(properties[i], flags); 
       index = null; 
      } 
      else 
      { 
       property = 
        type.GetProperty(properties[i].Replace(string.Format("[{0}]", indexValue), string.Empty), 
         flags); 
       index = GetIndex(indexValue, property); 
      } 

      if (i < properties.Length - 1) 
       instance = property.GetValue(instance, index); 
      type = instance.GetType(); 
     } 

     property.SetValue(instance, value, index); 
    } 

    public static object GetProperty(object instance, string propery) 
    { 
     const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 
     var properties = propery.Split('.'); 
     var type = instance.GetType(); 

     foreach (var p in properties) 
     { 
      var indexValue = Regex.Match(p, @"(?<=\[)(.*?)(?=\])").Value; 

      object[] index; 
      PropertyInfo property; 
      if (string.IsNullOrEmpty(indexValue)) 
      { 
       property = type.GetProperty(p, flags); 
       index = null; 
      } 
      else 
      { 
       property = 
        type.GetProperty(p.Replace(string.Format("[{0}]", indexValue), string.Empty), 
         flags); 
       index = GetIndex(indexValue, property); 
      } 

      instance = property.GetValue(instance, index); 
      type = instance.GetType(); 
     } 

     return instance; 
    } 

    private static object[] GetIndex(string indicesValue, PropertyInfo property) 
    { 
     var parameters = indicesValue.Split(','); 
     var parameterTypes = property.GetIndexParameters(); 
     var index = new object[parameterTypes.Length]; 

     for (var i = 0; i < parameterTypes.Length; i++) 
      index[i] = parameterTypes[i].ParameterType.IsEnum 
       ? Enum.Parse(parameterTypes[i].ParameterType, parameters[i]) 
       : Convert.ChangeType(parameters[i], parameterTypes[i].ParameterType); 

     return index; 
    } 
} 

,這裏是一些例子:

public enum Qwerty 
    { 
     Q,W,E,R,T,Y 
    } 

    class A 
    { 
     private int[,] _array=new int[10,10]; 

     public B PropertyB { get; set; } 

     public int this[int i, int j] 
     { 
      get { return _array[i, j]; } 
      set { _array[i, j] = value; } 
     } 
    } 

    class B 
    { 
     public int Value { get; set; } 
    } 

嵌套屬性:

 var a = new A { PropertyB = new B() }; 
     Helper.SetProperty(a, "PropertyB.Value", 100); 
     var value = Helper.GetProperty(a, "PropertyB.Value"); 

索引(具有多個索引):

 var a = new A { PropertyB = new B() }; 
     Helper.SetProperty(a, "Item[1,1]", 100); 
     var value = Helper.GetProperty(a, "Item[1,1]"); 

解釋:

 var list = new List<int>() { 0, 1, 2, 3, 4 }; 
     Helper.SetProperty(list, "Item[2]", 200); 
     var value = Helper.GetProperty(list, "Item[2]"); 

使用列表嵌套屬性:

 var list = new List<A>() { new A { PropertyB = new B() } }; 
     Helper.SetProperty(list, "Item[0].PropertyB.Value", 75); 
     var value = Helper.GetProperty(list, "Item[0].PropertyB.Value"); 

字典:

 var dic = new Dictionary<int, A> { { 100, new A { PropertyB = new B() } } }; 
     var newA = new A { PropertyB = new B() { Value = 45 } }; 
     Helper.SetProperty(dic, "Item[100]", newA); 
     var value = Helper.GetProperty(dic, "Item[100].PropertyB.Value"); 

詞典與枚舉的關鍵:

var dic = new Dictionary<Qwerty, A> { { Qwerty.Q, new A { PropertyB = new B() } } }; 
    var newA = new A { PropertyB = new B() { Value = 45 } }; 
    Helper.SetProperty(dic, "Item[Q]", newA); 
    var value = Helper.GetProperty(dic, "Item[Q].PropertyB.Value"); 

枚舉作爲價值:

var list = new List<Qwerty>() { Qwerty.Q, Qwerty.W, Qwerty.E, Qwerty.R, Qwerty.T, Qwerty.Y }; 
    Helper.SetProperty(list, "Item[2]", Qwerty.Q); 
    var value = Helper.GetProperty(list, "Item[2]"); 
+0

嘿,謝謝你的代碼。當我找不到我認爲我會找到的東西時,我總是會有點懷疑。種類表示這不是需要解決方案的問題。但是我找不到替代方案,所以我會繼續編碼。非常感謝。 – gurun 2014-09-23 00:06:29