我读了一个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)
}
答案 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
类型是错误的。你可以在反射调用中做一些验证,然后做出更恰当的反应。不幸的是,没有办法在编译时验证这一点。