2011-04-16 171 views
0

我需要調用SetSettings()並使用splitSettings中的3個元素,將EncodeAudio設置爲False。 我該怎麼做呢?將對象的屬性轉換爲我在字符串中擁有的名稱。 我意識到我可以用switch語句來處理所有設置,但必須採取更加動態的方式來執行此操作。將對象名稱空間和名稱轉換爲對象

namespace SettingsLib 
{ 
    public class Settings 
    { 
    public Boolean EncodeAudio { get; set; } 
    } 
} 
namespace Service 
{ 
    void SetSettings() 
    { 
    string[] splitSettings = { "SettingsLib.Settings", "EncodeAudio", "False" }; 
    // Need to set EncodeAudio to False in SettingsLib.Settings 
    } 
} 

是的,我有設置

說的一個實例:

Settings settingManager = new Settings(); 

我試圖做使用splitSettings的元素是動態設置的EncodeAudo爲False

settingManager.EncodeAudio = False; 

感謝TBohnen.jnr 的幫助,我來到這個答案:

public void setProperty(object containingObject, string propertyName, object newValue) 
{ 
    foreach (PropertyInfo p in containingObject.GetType().GetProperties()) 
    { 
     if (p.Name == propertyName) 
     { 
      p.SetValue(containingObject, Convert.ChangeType(newValue, p.PropertyType), null); 
     } 
    } 
} 
+1

你的設置對象的某個實例是否在某處?如果不這樣做,嘗試這樣做是沒有意義的。動態地嘗試按名稱創建該對象的實例將是可行的。那是你正在嘗試做什麼? – 2011-04-16 19:39:43

+0

或者EncodeAudio方法應該是靜態的嗎? – joce 2011-04-16 19:50:21

+0

即使它是靜態的,我如何從字符串的名稱中找到要使用的屬性? – jpiccolo 2011-04-16 19:53:44

回答

0

編輯與詮釋測試它,布爾人,雙人和字符串,它的工作,還添加了一個檢查以確保該屬性存在並拋出異常(不想要更改異常類型)

編輯2:臨時解決方案,將ad d更多typenames到轉換方法,或者如果有人可以建議一個更動態的方式來鑄造它(如果不是,那麼我假設你將不得不知道所有將被使用的類型)?

EDIT3從問題的另一個答案(克里斯·泰勒)偷了轉換方法,謝謝:-)

public void setProperty(object containingObject, string propertyName, object newValue) 
    { 
     if (containingObject.GetType().GetProperties().Count(c => c.Name == propertyName) > 0) 
     { 
      var type = containingObject.GetType().GetProperties().First(c => c.Name == propertyName).PropertyType; 
      object val = Convert(type,(string)newValue); 
      containingObject.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, containingObject, new object[] { val }); 
     } 
     else 
     { 
      throw new KeyNotFoundException("The property: " + propertyName + " was not found in: " + containingObject.GetType().Name); 
     } 
    } 

    public object convert(System.Type type, string value) 
    { 
     return Convert.ChangeType(value, type); 

    } 

http://www.haslo.ch/blog/setproperty-and-getproperty-with-c-reflection/

感興趣採取看,如果這個工程,創建快速測試:

class testSettings 
{ 
    public bool SetBool { get; set; } 

    public void setProperty(object containingObject, string propertyName, object newValue) 
    { 
     if (containingObject.GetType().GetProperties().Count(c => c.Name == propertyName) > 0) 
     { 
      containingObject.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, containingObject, new object[] { newValue }); 
     } 
     else 
     { 
      throw new KeyNotFoundException("The property: " + propertyName + " was not found in: " + containingObject.GetType().Name); 
     } 
    } 
} 

static void Main(string[] args) 
{ 
    testSettings ts = new testSettings(); 
    ts.SetBool = false; 
    ts.setProperty(ts, "SetBool", true); 
    Console.WriteLine(ts.SetBool.ToString()); 
    Console.Read(); 
} 

輸出是真實的,不完全確定它是否會正確轉換所有類型你GH。

+0

這是在正確的軌道上,但仍然不完整,你傳遞布爾真實的,我傳遞「真」,這是行不通的。 ts.setProperty(ts,「SetBool」,「true」); System.MissingMethodException失敗。現在我想我必須將字符串的值轉換爲正確的類型。 – jpiccolo 2011-04-16 20:46:08

+0

@jpiccolo添加轉換方法和更改爲setProperty,應該現在工作... – 2011-04-16 21:14:57

+0

是啊,我正在研究這個問題,並得出了相同的解決方案: public void setProperty(object containsObject,string propertyName,object newValue) { 的foreach(在containingObject.GetType的PropertyInfo p()。的GetProperties()) { 如果(p.Name == propertyName的) { p.SetValue(containingObject,Convert.ChangeType(NEWVALUE,p.PropertyType) , 空值); } } } – jpiccolo 2011-04-16 21:16:41

0

也許你應該標記您可設置的屬性爲static,然後嘗試使用反射來設置值:

namespace SettingsLib 
{ 
    public static class Settings 
    { 
    public static bool EncodeAudio { get; set; } 
    } 
} 
namespace Service 
{ 
    void SetSettings() 
    { 
    string[] splitSettings = { "SettingsLib.Settings", "EncodeAudio", "False" }; 
    dynamic property = Type.GetType(splitSettings[0]).GetProperty(splitSettings[1]); 
    property = splitSettings[2]; 
    } 
} 
0

正如其他人所說的,你應該考慮讓你的SettingsLib類是靜態的。而且您可能還需要處理從字符串到目標類型的值轉換。這是一個簡單的例子,這將如何工作。

namespace Service 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     string[] splitSettings = { "SettingsLib.Settings", "EncodeAudio", "False" }; 
     SetProperty(splitSettings[0], splitSettings[1], splitSettings[2]); 
    } 

    static void SetProperty(string typeName, string propertyName, object value) 
    { 
     var type = Type.GetType(typeName); 
     if (type == null) 
     { 
     throw new ArgumentException("Unable to get type", "typeName"); 
     } 

     var pi = type.GetProperty(propertyName); 
     if (pi == null) 
     { 
     throw new ArgumentException("Unable to find property on type", "propertyName"); 
     } 

     object propertyValue = value; 

     if (propertyValue != null) 
     { 
     // You might need more elaborate testing here to ensure that you can handle 
     // all the various types, you might need to special case some types here 
     // but this will work for the basics. 
     if (pi.PropertyType != propertyValue.GetType()) 
     { 
      propertyValue = Convert.ChangeType(propertyValue, pi.PropertyType); 
     } 
     } 

     pi.SetValue(null, propertyValue, null); 
    } 
    } 
} 

namespace SettingsLib 
{ 
    public static class Settings 
    { 
    public static bool EncodeAudio { get; set; }  
    } 
} 
+0

Type.GetType(typeName)總是返回null。即使類設置和屬性是靜態的。 – jpiccolo 2011-04-16 20:57:14

+0

感謝Convert.ChangeType,這會爲我節省一些時間在過去:-) – 2011-04-16 21:21:58

+0

@jpiccolo,如果GetType(typeName)返回null,這意味着您傳遞的類型名稱不匹配鍵入您正在嘗試訪問。您可以使用ILDASM或Reflector來檢查您是否使用了正確的名稱。 – 2011-04-17 08:12:59