c#用变量选择类属性?

时间:2009-04-27 09:05:51

标签: c# .net reflection

我正在为我们现有的(但已损坏的)系统添加功能。它从Web服务中获取XML文件,解析它然后在将它打包回我们的数据库之前做一些事情。

之前的开发人员(现已离职)给我留下了这个小宝石:

http://dl.getdropbox.com/u/109069/wut.GIF

我想知道是否有办法解决这个问题?

我可以遍历每个节点并通过名称分配给wo对象吗?

像这样的东西(伪代码):

   foreach XmlNode xn in WorkorderNodeTree
        {
            //find out the property name of the current node
            //match to the property in the workorder class
            //set the value equal

            wo.<xn.name> = xn.innertext

        }

现在我发现的唯一接近的是(来自互联网):

 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);


    }

但它在o上返回一个空引用异常。我有点困惑,有什么提示吗?

我认为这样做,我需要使用反射或泛型,但我以前从未碰过这些东西 - 任何人都可以建议任何可能指向正确方向或至少试图解释反思的东西吗?

非常感谢所有人,为可怕的长篇帖子道歉!

编辑:

谢谢,非常深刻和真诚的感谢Fredrik和Rytmis - 你们两个都是我单调的办公环境中的白衣骑士。 Rytmis的代码编辑已经解决了这个问题,但是我在这个小时左右学到了很多东西 - 谢谢大家,非常感谢。

7 个答案:

答案 0 :(得分:1)

AutoMapper中尝试BLToolkit或自定义映射。

答案 1 :(得分:1)

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

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);
}

[edit]您可能还想指定一些绑定标志:

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

可能需要也可能不需要。我永远不会记得默认值是什么。 :)

答案 2 :(得分:1)

如何让xml序列化(System.Xml.Serialization.XmlSerializer)为您完成工作?根据xml,您可以简单地使用Deserialize方法返回从xml数据初始化的WorkOrder对象。如果您获得的xml没有直接映射到WorkOrder,您可以尝试使用WorkOrder上的各种Xml属性来对类进行更多控制,以便更好地控制WorkOrder序列化的方式。您还可以查看DataContractSerializer,它更快,更灵活,但您没有像使用XmlSerialization那样对序列化进行过多的控制。

您还可以考虑向WorkOrder类添加一个静态方法,FromXml,它接受xml并返回WorkOrder对象。在内部,您可以使用反序列化,或者甚至可以简单地在开关中初始化属性而不会弄乱反射。

答案 3 :(得分:1)

叫我Silly先生,但你为什么不改变WorkOrder构造函数来取一个XmlNode参数,把所有丑陋的任务都写进去,然后像这样调用它:

WorkOrder wo = new WorkOrder(xmlnode);

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

弗雷德里克说,

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

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

答案 6 :(得分:0)

您不应该使用反射,使用现有的.Net序列化或保留(丑陋但有效)静态代码。

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