2014-09-21 2 views
0

У меня есть система, использующая динамическую конфигурацию динамически загружаемых типов.Порт BeanUtils для .NET

Система загружает типы на основе XML и создает экземпляры. Затем он считывает «свойства» из файла XML, устанавливая эти свойства в созданном экземпляре. В настоящее время он работает с простыми свойствами непосредственно на экземпляре, однако эти типы могут иметь иерархию параметров, неизвестных вызывающей части.

Я ищу библиотеку utils, похожую на Java BeanUtils [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

Смежные вопросы