2011-04-16 126 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