如何创建类型的实例并按名称设置成员值?

时间:2015-03-21 01:14:02

标签: c# .net

我读了一个XML来获取命令列表,其中每个命令都是这样的命令

<Read Id="3" LocationId="21"/>

<Transform transformId="45" source="string"/>

在我的XML反序列化器中,我现在正在设置所有命令对象并准备好执行它们。

Type cType = Assembly.GetExecutingAssembly().GetType("Processing." + command.Name.ToString());
ICommand commandObject = Activator.CreateInstance(cType);

当我使用Activator.CreateInstance时,有没有办法分配名为&#39; Id&#39;和&#39; LocationId&#39;值3和21?我事先并不知道我所在的ICommand和每个ICommand都有不同的成员(除了他们都只有一种方法)

喜欢(伪代码)

commandObject = Activator.CreateInstance(cType);
foreach( XMLAttribute attribute in Element){
    commandObject <- SetClassMember(attribute.Name, attribute.value)
}

2 个答案:

答案 0 :(得分:1)

动态变量类型已在运行时解析,如果您知道您的命令将始终包含您可以执行的Id和LocationId属性:

dynamic commandObject = Activator.CreateInstance(cType);
commandObject.Id = 3;
commandObject.LocationId = 21;

否则你必须使用反射来检查它是否存在:

PropertyInfo prop = commandObject.GetType().GetProperty("Id");
if(null != prop && prop.CanWrite)
{
    prop.SetValue(commandObject, 3, null);
}

答案 1 :(得分:1)

由于无法知道在运行之前必须设置哪些属性,因此我无法想到除了简单反射之外的更好的方法来设置它们。一个天真的实现可能有点像这样:

object commandObject = Activator.CreateInstance(cType);
cType.GetProperty("Id").SetValue(commandObject, 3, null);
cType.GetProperty("LocationId").SetValue(commandObject, 3, null);

这将根据您的样本设置属性。为了使它成为通用的,你可以在每个属性的循环中运行它(适应最后一次编辑):

object commandObject = Activator.CreateInstance(cType);
foreach(XMLAttribute attribute in Element){
    cType.GetProperty(attribute.Name).SetValue(commandObject, attribute.value, null);
}

一些警告。它不会在运行时检查任何内容,因为类型是动态确定的属性需要根据XML结构存在,所以此代码也可以随时抛出NullReferenceException类型是错误的。你可以在反射调用中做一些验证,然后做出更恰当的反应。不幸的是,没有办法在编译时验证这一点。