【问题标题】:How to serialize List<IFilter> (Nokia Imaging SDK)?如何序列化 List<IFilter> (Nokia Imaging SDK)?
【发布时间】:2014-12-19 16:00:17
【问题描述】:

我正在尝试使用 XML 序列化保存应用于图像的 IFilter(接口类型)列表,以便用户可以从他离开的位置编辑相同的图像。

[XmlRoot]
public class ImageProperties
{
    public string ImageName { get; set; }
    public string ImageFilePath { get; set; }
    public List<IFilter> Filters { get; set; }
}

这可能吗?是否有其他替代方法可以做到这一点?

【问题讨论】:

    标签: c# windows-phone-8 xml-serialization nokia-imaging-sdk lumia-imaging-sdk


    【解决方案1】:

    您可以使用IXmlSerializable 来实现这一点。假设您可以更改ImageProperties 类。

    在序列化时,您可以通过查看每个过滤器实例并查询它来获取类型。您可以将此类型信息存储在 XML 中,以便在阅读它时知道它是哪种类型,然后您可以为每个过滤器调用默认的 XML 序列化程序。

    这是一个可能的实现。

    public class ImageProperties : IXmlSerializable
    {
        public string ImageName { get; set; }
        public string ImageFilePath { get; set; }
        public List<IFilter> Filters { get; set; }
    
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }
    
        public void ReadXml(System.Xml.XmlReader reader)
        {
            string startEle = reader.Name;            
            reader.ReadStartElement();
            Filters = new List<IFilter>();
    
            do
            {
                switch (reader.Name)
                {
                    case "imgName":
                        ImageName = reader.ReadElementContentAsString();
                        break;
                    case "imgFilePath":
                        ImageFilePath = reader.ReadElementContentAsString();
                        break;
                    case "filters":
                        reader.ReadStartElement("filters");
                        while (reader.Name.Equals("iFilter"))
                        {
                            XmlSerializer filterSerializer = new XmlSerializer(Type.GetType(reader.GetAttribute("type")));
                            reader.ReadStartElement("iFilter");
                            Filters.Add((IFilter)filterSerializer.Deserialize(reader));
                            reader.ReadEndElement();
                        }
                        reader.ReadEndElement();
                        break; 
    
                    default:
                        reader.ReadOuterXml();
                        break;                  
                }
    
            } while (reader.Name != startEle);
        }
    
        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteElementString("imgName", ImageName);
            writer.WriteElementString("imgFilePath", ImageFilePath);
            writer.WriteStartElement("filters");            
            foreach (IFilter filter in Filters)
            {
                writer.WriteStartElement("iFilter");
                writer.WriteAttributeString("type", filter.GetType().FullName);
                XmlSerializer filterSerializer = new XmlSerializer(filter.GetType());
                filterSerializer.Serialize(writer, filter);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }
    }
    

    如果您有不同类型的过滤器,则会调用真实类型的默认序列化程序,因此它们的唯一属性将被记录。

    例如,这些过滤器类可用:

    public interface IFilter
    {
        string SomeCommonProp { get; set;}    
    }
    
    [XmlRoot("myFilter")]
    public class MyFilter : IFilter
    {
    
        [XmlElement("somemyFilterProp")]
        public string SomeMyFilterProp { get; set; }
    
        [XmlElement("someCommonProp")]
        public string SomeCommonProp { get; set;}
    }
    
    [XmlRoot("myOtherFilter")]
    public class MyOtherFilter : IFilter
    {
        [XmlElement("someOtherFilterProp")]
        public string SomeOtherFilterProp { get; set; }
    
        [XmlElement("someCommonProp")]
        public string SomeCommonProp { get; set;}
    }
    

    您可以使用如下方法将IFilters中的两种不同类型的过滤器序列化和反序列化为xml。

    static void Main(string[] args)
    {
        ImageProperties props = new ImageProperties();
        props.ImageName = "img.png";
        props.ImageFilePath = "c:\\temp\\img.png";
        props.Filters = new List<IFilter>();
        props.Filters.Add(new MyFilter() { SomeMyFilterProp = "x", SomeCommonProp ="p" });
        props.Filters.Add(new MyOtherFilter() { SomeOtherFilterProp = "y", SomeCommonProp ="p" });
    
        XmlSerializer s = new XmlSerializer(typeof(ImageProperties));
        using (StreamWriter writer = new StreamWriter(@"c:\temp\imgprops.xml"))
            s.Serialize(writer, props);
    
        using (StreamReader reader = new StreamReader(@"c:\temp\imgprops.xml"))
        {
            object andBack = s.Deserialize(reader);
        }
    
        Console.ReadKey();
    }
    

    这会生成一个如下所示的 XML。

    <?xml version="1.0" encoding="utf-8"?>
    <ImageProperties>
      <imgName>img.png</imgName>
      <imgFilePath>c:\temp\img.png</imgFilePath>
      <filters>
        <iFilter type="SomeNameSpace.Whatever.MyFilter">
          <myFilter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <somemyFilterProp>x</somemyFilterProp>
            <someCommonProp>p</someCommonProp>
          </myFilter>
        </iFilter>
        <iFilter type="SomeNameSpace.Whatever.MyOtherFilter">
          <myOtherFilter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <someOtherFilterProp>y</someOtherFilterProp>
            <someCommonProp>p</someCommonProp>
          </myOtherFilter>
        </iFilter>
      </filters>
    </ImageProperties>
    

    【讨论】:

    • 如果 IFilter 具有取决于用户选择的变量怎么办?每个 IFilter 都有不同类型的变量。
    • IFilter 的真实类型的序列化程序被调用,因此假设它记录了该特定类型过滤器的所有相关信息,每个过滤器类型的所有唯一信息都会被保存和恢复。我已经扩展了这个例子来展示这一点。
    【解决方案2】:

    没有。接口实例不能被序列化。它不知道“反序列化”到的实现。在这种情况下,它将需要一个具体的类或自定义序列化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多