当前位置:  开发笔记 > 编程语言 > 正文

C#:从XML实例化类

如何解决《C#:从XML实例化类》经验,为你挑选了4个好方法。

我所拥有的是一组类,它们都实现了相同的接口,但在引擎盖下可能会有很大差异.我希望有一个配置文件控制在启动程序时哪些类进入集合,采取看起来像这样的东西:


把它变成:

blah = new class1();
blah.prop1="foo";
blah.prop2="bar";

以非常通用的方式.我不知道该怎么做的是prop1将配置文件中的字符串转换为代码中的实际属性访问器.在C#中是否有任何元编程工具允许这样做?



1> Rob Cooper..:

将类序列化到/从xml可能更容易,然后您可以简单地将XmlReader(正在读取您的配置文件)传递给反序列化器,它将为您完成剩下的工作.

这是关于序列化的一篇非常好的文章

编辑

有一件事我想补充一点,即使反射很强大,它也需要你知道关于类型的一些东西,比如参数等.

序列化为XML不需要任何这些,并且您可以通过确保将完全限定的类型名称写入XML文件来保持类型安全,因此会自动加载相同的类型.



2> Lars Truijen..:

反射允许你这样做.您还可以查看XML序列化.

Type type = blah.GetType();
PropertyInfo prop = type.GetProperty("prop1");
prop.SetValue(blah, "foo", null);



3> Brian Ensink..:

我还建议其他人已经提到的Xml序列化.这是一个我一起展示的样本.属性用于将Xml中的名称连接到数据结构中的实际属性名称和类型.属性还列出了可以进入Things集合的所有允许类型.此集合中的所有内容都必须具有公共基类.你说你已经有了一个通用的接口 - 但是你可能不得不把它改成一个抽象的基类,因为这个代码示例在Thing接口时没有立即起作用.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            string xml =
                "" + 
                "" +
                "" + 
                "  " +
                "  " +
                "" +
                "";
            StringReader sr = new StringReader(xml);
            XmlSerializer xs = new XmlSerializer(typeof(ThingCollection));
            ThingCollection tc = (ThingCollection)xs.Deserialize(sr);

            foreach (Thing t in tc.Things)
            {
                Console.WriteLine(t.ToString());
            }
        }
    }

    public abstract class Thing
    {
    }

    [XmlType(TypeName="class1")]
    public class SomeThing : Thing
    {
        private string pn1;
        private string pn2;

        public SomeThing()
        {
        }

        [XmlAttribute("prop1")]
        public string PropertyNumber1
        {
            get { return pn1; }
            set { pn1 = value; }
        }

        [XmlAttribute("prop2")]
        public string AnotherProperty
        {
            get { return pn2; }
            set { pn2 = value; }
        }
    }

    [XmlType(TypeName="class2")]
    public class SomeThingElse : SomeThing
    {
        private int answer;

        public SomeThingElse()
        {
        }

        [XmlAttribute("prop3")]
        public int TheAnswer
        {
            get { return answer; }
            set { answer =value; }
        }
    }

    [XmlType(TypeName = "config")]
    public class ThingCollection
    {
        private List things;

        public ThingCollection()
        {
            Things = new List();
        }

        [XmlArray("stuff")]
        [XmlArrayItem(typeof(SomeThing))]
        [XmlArrayItem(typeof(SomeThingElse))]
        public List Things
        {
            get { return things; }
            set { things = value; }
        }
    }
}



4> Markus Olsso..:

您正在寻找反射或XML序列化.

使用反射,您可以使用类似的东西查找类型

public IYourInterface GetClass(string className)
{
    foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) 
    {            
        foreach (Type type in asm.GetTypes())
        {
            if (type.Name == className)
                return Activator.CreateInstance(type) as IYourInterface;
        }   
    }

    return null;
}

请注意,这将遍历所有程序集.您可能希望将其减少为仅包含当前正在执行的程序集.

要分配属性值,还可以使用反射.有点像

IYourInterface o = GetClass("class1");
o.GetType().GetProperty("prop1").SetValue(o, "foo", null);

虽然反射可能是最灵活的解决方案,但您还应该看看XML序列化,以便自己跳过繁重的工作.

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有