2

XML 직렬화를 사용하여 이미지에 적용된 IFilter (Interface 유형) 목록을 저장하려고합니다. 사용자가 중단 한 위치에서 동일한 이미지를 편집 할 수 있습니다.<IFilter> (Nokia Imaging SDK) 목록을 직렬화하는 방법은 무엇입니까?

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

이것은 가능합니까? 같은 일을하는 또 다른 대안이 있습니까?

답변

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

다른 유형의 필터가있는 경우 실제 유형의 기본 serializer가 호출되므로 고유 한 속성이 기록됩니다. 사용할 수 이러한 필터 클래스와 예를 들어

:

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

에는 직렬화 및 XML에 IFilter를에 필터의 두 가지 유형을 deserialise하기 위해 다음과 같이 사용할 수 있습니다.

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> 
+0

IFilter에 사용자 선택에 따른 변수가 있다면 어떻게 될까요? 각 IFilter에는 다른 종류의 변수가 있습니다. – venu238

+0

실제 형식의 IFilter에 대한 serializer가 호출되므로이 특정 유형의 필터에 대한 모든 관련 정보가 기록된다고 가정하면 각 필터 유형에 대한 모든 고유 정보가 보존되고이 정보로 복원됩니다. 이것을 보여주기 위해 예제를 확장했습니다. – steve16351

1

아니요. 인터페이스 인스턴스를 직렬화 할 수 없습니다. 그것은 "비 직렬화"할 구현을 알지 못합니다. 이 경우 구체적인 클래스 또는 사용자 지정 serialization이 필요합니다.