c#用变量选择类属性?

c#用变量选择类属性?,c#,.net,reflection,C#,.net,Reflection,我正在为我们现有的(但已损坏的)系统之一添加功能。它从web服务中获取XML文件,对其进行解析,然后在将其打包回数据库之前执行一些操作 以前的开发人员(现在已经离开)给我留下了一块小宝石: 我想知道有没有办法 我可以循环遍历每个节点并按其名称分配给wo对象吗 类似这样的代码(伪代码): 但它在o上返回空引用异常。我有点困惑,有什么建议吗 我假设要这样做,我需要使用反射或泛型,但我以前从未想到过这些东西——有人能给我提供一些建议,让我朝着正确的方向走,或者至少尝试解释反射吗 非常感谢大家,为这篇

我正在为我们现有的(但已损坏的)系统之一添加功能。它从web服务中获取XML文件,对其进行解析,然后在将其打包回数据库之前执行一些操作

以前的开发人员(现在已经离开)给我留下了一块小宝石:

我想知道有没有办法

我可以循环遍历每个节点并按其名称分配给wo对象吗

类似这样的代码(伪代码):

但它在o上返回空引用异常。我有点困惑,有什么建议吗

我假设要这样做,我需要使用反射或泛型,但我以前从未想到过这些东西——有人能给我提供一些建议,让我朝着正确的方向走,或者至少尝试解释反射吗

非常感谢大家,为这篇长得可怕的帖子道歉

编辑:


谢谢,非常深切和真诚地感谢弗雷德里克和雷特米斯——你们两个都是我单调的办公室环境中的白衣骑士。Rytmis的代码编辑解决了这个问题,但我在这一小时左右学到了很多-谢谢大家,非常感谢。

尝试以下代码来创建Workorder实例:

Workorder o = Activator.CreateInstance<Workorder>();
Workorder o=Activator.CreateInstance();

尝试以下代码来创建Workorder实例:

Workorder o = Activator.CreateInstance<Workorder>();
Workorder o=Activator.CreateInstance();
在中尝试或自定义映射。

在中尝试或自定义映射。

正如弗雷德里克所说

Workorder o = Activator.CreateInstance<Workorder>();
Workorder o=Activator.CreateInstance();
将修复空引用。复制属性的其余代码是正确的。

正如弗雷德里克所说

Workorder o = Activator.CreateInstance<Workorder>();
Workorder o=Activator.CreateInstance();

将修复空引用。复制属性的其余代码是正确的。

我认为您的代码可能需要一些调整

foreach (XmlNode xl in myXML)
{
    object o = Assembly.GetExecutingAssembly().CreateInstance("Workorder", true);
    Type t = xl.Name.GetType();
    PropertyInfo pi = t.GetProperty(xl.Name);
    pi.SetValue(o, xl.InnerText, null);
}
这将为您正在设置的每个属性创建一个新的WorkOrder实例,并尝试从Name.GetType()反映PropertyInfo,它实际上是typeof(String),而不是您希望的typeof(WorkOrder)。相反:

WorkOrder w = new WorkOrder();
Type t = typeof(WorkOrder);
foreach (XmlNode xl in myXML)
{
    PropertyInfo pi = t.GetProperty(xl.Name);
    pi.SetValue(w, xl.InnerText, null);
}
[编辑]您可能还需要指定一些绑定标志:

    PropertyInfo pi = t.GetProperty(xl.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);

这可能需要也可能不需要。我永远记不起默认设置是什么。:)

我认为您的代码可能需要一些调整

foreach (XmlNode xl in myXML)
{
    object o = Assembly.GetExecutingAssembly().CreateInstance("Workorder", true);
    Type t = xl.Name.GetType();
    PropertyInfo pi = t.GetProperty(xl.Name);
    pi.SetValue(o, xl.InnerText, null);
}
这将为您正在设置的每个属性创建一个新的WorkOrder实例,并尝试从Name.GetType()反映PropertyInfo,它实际上是typeof(String),而不是您希望的typeof(WorkOrder)。相反:

WorkOrder w = new WorkOrder();
Type t = typeof(WorkOrder);
foreach (XmlNode xl in myXML)
{
    PropertyInfo pi = t.GetProperty(xl.Name);
    pi.SetValue(w, xl.InnerText, null);
}
[编辑]您可能还需要指定一些绑定标志:

    PropertyInfo pi = t.GetProperty(xl.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);

这可能需要也可能不需要。我永远记不起默认设置是什么。:)

让xml序列化(System.xml.serialization.XmlSerializer)为您完成这项工作怎么样?根据xml的不同,您可以简单地使用反序列化方法,该方法返回从xml数据初始化的WorkOrder对象。如果得到的xml没有直接映射到WorkOrder,则可以尝试在WorkOrder to类上使用各种xml属性,以更好地控制WorkOrder序列化的方式。您还可以看看DataContractSerializer,它更快、更灵活,但您对序列化的控制不如对XmlSerialization的控制


您还可以考虑将一个静态方法添加到WorkOrdRead,FaseXML中,它采用XML和返回WorkOrthObjor对象。在内部,您可以使用反序列化,甚至可以简单地初始化交换机中的属性,而不影响反射

让xml序列化(System.xml.serialization.XmlSerializer)为您完成这项工作怎么样?根据xml的不同,您可以简单地使用反序列化方法,该方法返回从xml数据初始化的WorkOrder对象。如果得到的xml没有直接映射到WorkOrder,则可以尝试在WorkOrder to类上使用各种xml属性,以更好地控制WorkOrder序列化的方式。您还可以看看DataContractSerializer,它更快、更灵活,但您对序列化的控制不如对XmlSerialization的控制


您还可以考虑将一个静态方法添加到WorkOrdRead,FaseXML中,它采用XML和返回WorkOrthObjor对象。在内部,您可以使用反序列化,甚至可以简单地初始化交换机中的属性,而不影响反射

叫我傻先生,但为什么不更改WorkOrder构造函数,以获取一个
XmlNode
参数,将所有难看的赋值放入其中,然后像这样调用它:

WorkOrder wo = new WorkOrder(xmlnode);

你可以叫我傻先生,但是为什么不改变WorkOrder构造函数来获取一个
XmlNode
参数,把所有难看的赋值都放进去,然后像这样调用它:

WorkOrder wo = new WorkOrder(xmlnode);

您不应该使用反射、使用现有的.Net序列化或留下(丑陋但工作正常的)静态代码


除了字符串以外的其他类型呢?如果xml格式不匹配怎么办?

您不应该使用反射、使用现有的.Net序列化或保留(丑陋但工作正常的)静态代码


除了字符串以外的其他类型呢?如果xml格式不匹配怎么办?

请注意,您需要获取Workorder的类型对象,而不是从xl.Name获取,因为您需要Workorder类型中某个属性的属性信息。Fredrik,感谢您的快速响应,我如何从Workorder获取类型对象?因为这个类上没有GetType()方法。对不起,我刚从大学毕业,这里没有人用过反射!非常感谢您的帮助。Gareth:NET中的所有对象都有GetType方法(它们都从Object继承它。另一种方法是使用typeof:Type t=typeof(Workorder)-该方法也适用于.NET中的所有对象。我不好,我的意思是我没有更改/覆盖.NET方法。感谢您的帮助,我将尝试t=typeof(Workorder)方法。请注意,您将希望获得Workorder的类型对象,而不是从xl.Name获得,因为您希望在