2016-07-13 6 views
1

제네릭 클래스의 XML을 만들고 싶습니다. 속성 중 하나에 제네릭 형식이 있습니다. 이 속성의 경우 XML 요소 이름으로 속성 이름을 사용하지 않고 제네릭 형식의 이름을 사용합니다.C# : 제네릭 형식 이름의 XML 요소 이름을 갖는 가장 좋은 방법

클래스는 다음과 같습니다

[XmlRoot("Entity")] 
public class StoreItem<TEntity> 
    where TEntity : class, new() 
{ 
    /// <summary> 
    /// Gets and sets the status of the entity when storing. 
    /// </summary> 
    [XmlAttribute] 
    public System.Data.Services.Client.EntityStates Status { get; set; } 

    /// <summary> 
    /// Gets and sets the entity to be stored. 
    /// </summary> 
    public TEntity Entity { get; set; } 
} 

는 XML 같은 것을 포함해야 종류 StoreItem<SewageArea>의 저장 항목 직렬화 : 위의 예에서 SewageArea

<Entity Status="Deleted"> 
    <SewageArea ...> 
     ... 
    </SewageArea> 
<Entity> 

요구 사항은을 그 "보통"방식으로 직렬화되어야합니다. 또 다른 중요한 점은 해당 코드가 StoreItem 클래스에 새로 추가 된 속성을 자동으로 직렬화 할 준비가되어 있어야한다는 것입니다.

+0

너무 쉽지 않습니다. [XML에 직렬화 할 때 클래스 이름 바꾸기] (https://stackoverflow.com/questions/36745144/rename-class-when-serializing-to-xml) 라인을 따라 뭔가를하고 싶지만 속성 인수 제네릭 형식 매개 변수를 포함 할 수 없습니다. 즉, [[XmlElement (typeof (TEntity))]'는 컴파일되지 않습니다. – dbc

+0

나는 그것이 곧장 나아지지 않는다는 것을 안다. 나는 IXmlSerialisable 인터페이스를 구현하는 것에 대해 생각했지만 엔티티 객체의 "정상적인"직렬화와 다른 속성의 자동 직렬화를 수행 할 때 멈추었다. – scher

답변

6

Rename class when serializing to XML 행을 따라 무언가를하고 싶지만 속성 인수에 제네릭 유형 매개 변수 (예 : [XmlElement(typeof(TEntity))])가 포함될 수 없습니다. 그리고 구현의 확실한 대안은 StoreItem<TEntity>에 추가 된 속성의 자동 직렬화를 잃어 버리기 때문에 불편합니다.

[XmlRoot("Entity")] 
public class StoreItem<TEntity> 
    where TEntity : class, new() 
{ 
    /// <summary> 
    /// Gets and sets the status of the entity when storing. 
    /// </summary> 
    [XmlAttribute] 
    public System.Data.Services.Client.EntityStates Status { get; set; } 

    /// <summary> 
    /// Gets and sets the entity to be stored. 
    /// </summary> 
    [XmlIgnore] 
    public TEntity Entity { get; set; } 

    [XmlAnyElement] 
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)] 
    public XElement XmlEntity 
    { 
     get 
     { 
      return (Entity == null ? null : XObjectExtensions.SerializeToXElement(Entity, null, true)); 
     } 
     set 
     { 
      Entity = (value == null ? null : XObjectExtensions.Deserialize<TEntity>(value)); 
     } 
    } 
} 

확장 방법 사용 :

public static class XObjectExtensions 
{ 
    public static T Deserialize<T>(this XContainer element) 
    { 
     return element.Deserialize<T>(null); 
    } 

    public static T Deserialize<T>(this XContainer element, XmlSerializer serializer) 
    { 
     using (var reader = element.CreateReader()) 
     { 
      serializer = serializer ?? new XmlSerializer(typeof(T)); 
      object result = serializer.Deserialize(reader); 
      if (result is T) 
       return (T)result; 
     } 
     return default(T); 
    } 

    public static XElement SerializeToXElement<T>(this T obj) 
    { 
     return obj.SerializeToXElement(null, true); 
    } 

    public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer, bool omitStandardNamespaces) 
    { 
     var doc = new XDocument(); 
     using (var writer = doc.CreateWriter()) 
     { 
      XmlSerializerNamespaces ns = null; 
      if (omitStandardNamespaces) 
       (ns = new XmlSerializerNamespaces()).Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines. 
      serializer = serializer ?? new XmlSerializer(obj.GetType()); 
      serializer.Serialize(writer, obj, ns); 
     } 
     var element = doc.Root; 
     if (element != null) 
      element.Remove(); 
     return element; 
    } 
} 
을 대신 다음과 같이

은, 당신이 할 수있는 일은, [XmlAnyElement] 대리 재산의 사용이 TEntity중첩 된 직렬화을 할 수 있도록하는 것입니다

알 수없는 모든 요소에 대해 [XmlAnyElement] 속성이 호출되므로 어떤 이유로 든 XML에서 예기치 않은 요소가있는 경우에서 예외가 발생할 수 있습니다 루트 요소 이름이 잘못 되었기 때문에입니다. 가능성이있는 경우이 메서드에서 예외를 catch하고 무시할 수 있습니다.

그런 다음, 샘플 TEntity 클래스

public class SewageArea 
{ 
    public double Area { get; set; } 
} 

위한 XML 출력은 다음과 같습니다

<Entity Status="State1"> 
    <SewageArea> 
    <Area>10101</Area> 
    </SewageArea> 
</Entity> 

샘플 fiddle.

+0

귀하의 자세한 공감에 감사드립니다. 나는 그것을 구현하고 테스트 할 것이다. – scher