将对象名称空间和名称转换为对象
我需要调用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);
}
}
}
编辑与诠释测试它,布尔人,双人和字符串,它的工作,还添加了一个检查以确保该属性存在并抛出异常(不想要更改异常类型)
编辑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。
这是在正确的轨道上,但仍然不完整,你传递布尔真实的,我传递“真”,这是行不通的。 ts.setProperty(ts,“SetBool”,“true”); System.MissingMethodException失败。现在我想我必须将字符串的值转换为正确的类型。 – jpiccolo 2011-04-16 20:46:08
@jpiccolo添加转换方法和更改为setProperty,应该现在工作... – 2011-04-16 21:14:57
是啊,我正在研究这个问题,并得出了相同的解决方案: 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
也许你应该标记您可设置的属性为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];
}
}
正如其他人所说的,你应该考虑让你的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; }
}
}
Type.GetType(typeName)总是返回null。即使类设置和属性是静态的。 – jpiccolo 2011-04-16 20:57:14
感谢Convert.ChangeType,这会为我节省一些时间在过去:-) – 2011-04-16 21:21:58
@jpiccolo,如果GetType(typeName)返回null,这意味着您传递的类型名称不匹配键入您正在尝试访问。您可以使用ILDASM或Reflector来检查您是否使用了正确的名称。 – 2011-04-17 08:12:59
你的设置对象的某个实例是否在某处?如果不这样做,尝试这样做是没有意义的。动态地尝试按名称创建该对象的实例将是可行的。那是你正在尝试做什么? – 2011-04-16 19:39:43
或者EncodeAudio方法应该是静态的吗? – joce 2011-04-16 19:50:21
即使它是静态的,我如何从字符串的名称中找到要使用的属性? – jpiccolo 2011-04-16 19:53:44