2016-12-06 36 views
0

我工作的一個項目,我需要能夠做到以下幾點:如何動態地賦值給嵌套對象?

說,我們Aa類是配置類:

public class Aa 
{ 
    public Bb BbName { set; get; } 
    public string Dd { set; get; } 
} 


public class Bb 
{ 
    public string bb { set; get; } 
    public string cc { set; get; } 
} 

我想在來從環境變量爲了將它們分配給相應的屬性。這是我的意思:作爲Environment.GetEnvironmentVariable的模擬,我們使用Dictionary<string, string>。 安裝程序將是這樣的:

var dic = new Dictionary<string, string>(); 
dic.Add("Dd", "236.154"); 
dic.Add("BbName.bb", "value_for_Bb.bb"); // as you can see, I'm using nested object's full 
dic.Add("BbName.cc", "value_for_Bb.cc"); // path, in order to be able to identify it 

然後我寫了一個方法,它看起來像這樣:

private static void ReadPropertiesRecursive<T>(T obj, Type type, List<string> prefixes) 
{ 

    foreach (PropertyInfo property in type.GetProperties()) 
    { 
     if (property.PropertyType.GetTypeInfo().IsClass && property.PropertyType != typeof(string)) 
     { 
      prefixes.Add(property.Name); 
      ReadPropertiesRecursive(obj, property.PropertyType, prefixes); 
      prefixes.Remove(property.Name); 
     } 
     else 
     { 
      var propertyFullName = prefixes != null && prefixes.Count > 0 ? $"{prefixes.Aggregate((i, j) => i + "." + j)}.{property.Name}" : property.Name; 

      property.SetValue(obj, dic[propertyFullName]); 

      Console.WriteLine(propertyFullName); // just for debugging 
     } 
    } 
} 

因此,使用遞歸,我能夠達到給定的Type的所有嵌套對象唯一剩下的就是給它們分配相應的值。我試圖在property.SetValue(obj, dic[propertyFullName]);上這樣做,但它會拋出一個錯誤,並且它是有道理的:obj是一個「根」對象,而不是我想直接指定值的那個對象。所以,我可能需要通過這裏不obj,而是property,這是obj的屬性的實例。那是對的嗎?這會工作嗎?如果是的話,我該怎麼做?

+2

拆分屬性名稱以 「」並讓你的函數遞歸。 –

+0

這就是我正在做的,我正確地做到了 - 我知道,因爲我可以在打印出'propertyFullName'時看到它。 – nicks

+0

啊,你說**拆分**屬性名稱......我很抱歉,我不明白你到底在說什麼,或者它如何幫助我。 – nicks

回答

0

該訣竅:

private static void ReadPropertiesRecursive<Tt>(Tt obj, Type type, List<string> prefixes) 
{ 

    foreach (PropertyInfo property in type.GetProperties()) 
    { 
     if (property.PropertyType.GetTypeInfo().IsClass && property.PropertyType != typeof(string)) 
     { 
      prefixes.Add(property.Name); 
      var val = property.GetValue(obj); 
      if (val == null) 
       val = Activator.CreateInstance(property.PropertyType); 
      property.SetValue(obj, val); 
      ReadPropertiesRecursive(val, property.PropertyType, prefixes); 
      prefixes.Remove(property.Name); 
     } 
     else 
     { 
      var propertyFullName = prefixes != null && prefixes.Count > 0 ? $"{prefixes.Aggregate((i, j) => i + "." + j)}.{property.Name}" : property.Name; 

      property.SetValue(obj, dic[propertyFullName]); 

      Console.WriteLine(propertyFullName); 
     } 
    } 
}