Вы можете использовать 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;}
}
Вы можете использовать следующую сериализацию и deserialise два различных типа фильтра 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 имеет разные переменные. – venu238
Вызывается сериализатор для реального типа IFilter, поэтому, если предположить, что он записывает всю соответствующую информацию об этом конкретном типе фильтра, вся уникальная информация для каждого типа фильтра сохраняется и восстанавливается с этим. Я расширил этот пример, чтобы показать это. – steve16351