将XML文档反序列化为带有动态加载程序集类型的.net对象



我正在做一个项目,我在一个核心程序集中有一系列配置类,我想让用户能够通过创建XML文档来创建配置对象的实例。

为此,我正在考虑为基类创建xsd文件。

我的下一个问题是,我有一些程序集是动态加载的,在设计时不知道。它们都将实现一组通用的接口。

最大的问题是我如何创建一个对象图实例化嵌套类型从动态加载的程序集?

<mycoreobject>
  <somethings>
  <ass1:plugintype1 att="aaa"/> //implementing ISomthing from dynamically loaded assembly
  </somethings>
</mycoreobject>

最终的结果,我想要一个核心的mycoreobject对象与issomethings的列表,这些issomethings实际上是实例化为各自程序集的类型。

在XAML中,我们通过定义名称空间来做类似的事情,每个名称空间引用一个特定的程序集。在我的示例中,ass1将是外部程序集的别名。

我写的越多,我就越认为我只需要分析XML内容并手动构建对象图?

欢迎提出任何建议、想法或解决方案。

Tia

山姆

像这样?

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
public class MyBase
{
}
public class ConcreteType : MyBase
{
    [XmlAttribute("att")]
    public string Value { get; set; }
}
[XmlRoot("mycoreobject")]
public class SomeRoot
{
    public List<MyBase> Items { get; set; }
}
static class Program
{
    static void Main()
    {
        XmlAttributeOverrides xao = new XmlAttributeOverrides();
        XmlAttributes extraTypes = new XmlAttributes();
        extraTypes.XmlArray = new XmlArrayAttribute("somethings");
        // assume loaded dynamically, along with name/namespace
        extraTypes.XmlArrayItems.Add(new XmlArrayItemAttribute("plugintype1",
            typeof(ConcreteType)) { Namespace = "my-plugin-namespace" });
        xao.Add(typeof(SomeRoot), "Items", extraTypes);
        // important: need to cache and re-use "ser", or will leak assemblies
        XmlSerializer ser = new XmlSerializer(typeof(SomeRoot), xao);
        //example 1: writing
        var obj = new SomeRoot { Items = new List<MyBase> { new ConcreteType { Value = "abc" } } };
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        ns.Add("ass1", "my-plugin-namespace");
        ser.Serialize(Console.Out, obj, ns);
        // example 2: reading
        string xml = @"<mycoreobject xmlns:ass1=""my-plugin-namespace"">
  <somethings>
  <ass1:plugintype1 att=""aaa""/>
  </somethings>
</mycoreobject>";
        obj = (SomeRoot)ser.Deserialize(new StringReader(xml));
        var foundIt = (ConcreteType)obj.Items.Single();
        Console.WriteLine();
        Console.WriteLine(foundIt.Value); // should be "aaa"       
    }
}

最新更新