다음을 통해 공유


XmlSerializer 클래스 사용

WCF(Windows Communication Foundation)는 두 가지 직렬화 기술을 사용하여 애플리케이션의 데이터를 클라이언트와 서비스 간에 전송되는 XML로 변환할 수 있습니다 DataContractSerializerXmlSerializer.

DataContractSerializer

기본적으로 WCF는 클래스를 DataContractSerializer 사용하여 데이터 형식을 serialize합니다. 이 serializer는 다음 형식을 지원합니다.

  • 기본 형식(예: 정수, 문자열 및 바이트 배열)뿐만 아니라 기본 형식으로 처리되는 일부 특수 형식(예: XmlElementDateTime)입니다.

  • 데이터 계약 형식(특성으로 DataContractAttribute 표시된 형식).

  • SerializableAttribute 속성이 표시된 형식 중에는 ISerializable 인터페이스를 구현하는 형식도 포함됩니다.

  • IXmlSerializable 인터페이스를 구현하는 형식.

  • 많은 제네릭 컬렉션 유형을 포함하는 여러 일반적인 컬렉션 유형이 있습니다.

많은 .NET Framework 형식은 후자의 두 범주에 속하므로 직렬화할 수 있습니다. 직렬화 가능한 형식의 배열도 직렬화할 수 있습니다. 전체 목록은 서비스 계약에서 데이터 전송 지정을 참조하세요.

데이터 계약 형식과 함께 사용되는 이 DataContractSerializer방법은 새 WCF 서비스를 작성하는 데 권장되는 방법입니다. 자세한 내용은 데이터 계약 사용을 참조하세요.

XmlSerializer (XML 직렬화기)

WCF는 클래스도 지원합니다 XmlSerializer . 클래스는 XmlSerializer WCF에 고유하지 않습니다. ASP.NET 웹 서비스에서 사용하는 것과 동일한 serialization 엔진입니다. 클래스는 XmlSerializer 클래스보다 DataContractSerializer 훨씬 더 좁은 형식 집합을 지원하지만 결과 XML을 훨씬 더 많이 제어할 수 있으며 XSD(XML 스키마 정의 언어) 표준을 훨씬 더 많이 지원합니다. 또한 직렬화 가능한 형식에 선언적 특성이 필요하지 않습니다. 자세한 내용은 .NET Framework 설명서의 XML Serialization 항목을 참조하세요. 클래스는 XmlSerializer 데이터 계약 형식을 지원하지 않습니다.

Visual Studio에서 Svcutil.exe 또는 서비스 참조 추가 기능을 사용하여 타사 서비스에 대한 클라이언트 코드를 생성하거나 타사 스키마에 액세스하는 경우 적절한 serializer가 자동으로 선택됩니다. 스키마가 DataContractSerializer과(와) 호환되지 않으면 XmlSerializer이(가) 선택됩니다.

XmlSerializer로 전환

때때로 XmlSerializer으로 수동으로 전환해야 할 수 있습니다. 예를 들어 다음과 같은 경우에 발생합니다.

  • ASP.NET 웹 서비스에서 WCF로 애플리케이션을 마이그레이션하는 경우 새 데이터 계약 형식을 만드는 대신 호환되는 기존 XmlSerializer형식을 다시 사용할 수 있습니다.

  • 메시지에 표시되는 XML에 대한 정확한 제어가 중요하지만 WSDL(Web Services Description Language) 문서를 사용할 수 없는 경우(예: DataContractSerializer와 호환되지 않는 특정 표준화된 게시된 스키마를 준수해야 하는 형식으로 서비스를 만들 때)

  • 레거시 SOAP 인코딩 표준을 따르는 서비스를 만드는 경우

이러한 경우와 다른 상황에서, 다음 코드에 표시된 대로 서비스에 XmlSerializer 특성을 적용하여 수동으로 XmlSerializerFormatAttribute 클래스로 전환할 수 있습니다.

[ServiceContract]
[XmlSerializerFormat]
public class BankingService
{
[OperationContract]
    public void ProcessTransaction(BankingTransaction bt)
    {
        // Code not shown.
    }
}

//BankingTransaction is not a data contract class,
//but is an XmlSerializer-compatible class instead.
public class BankingTransaction
{
    [XmlAttribute]
    public string Operation;
    [XmlElement]
    public Account fromAccount;
    [XmlElement]
    public Account toAccount;
    [XmlElement]
    public int amount;
}
//Notice that the Account class must also be XmlSerializer-compatible.
<ServiceContract(), XmlSerializerFormat()> _
Public Class BankingService
    <OperationContract()> _
    Public Sub ProcessTransaction(ByVal bt As BankingTransaction)
        ' Code not shown.
    End Sub
End Class


' BankingTransaction is not a data contract class,
' but is an XmlSerializer-compatible class instead.

Public Class BankingTransaction
    <XmlAttribute()> _
    Public Operation As String
    <XmlElement()> _
    Public fromAccount As Account
    <XmlElement()> _
    Public toAccount As Account
    <XmlElement()> _
    Public amount As Integer
End Class
'Notice that the Account class must also be XmlSerializer-compatible.

보안 고려사항

비고

serialization 엔진을 전환할 때는 주의해야 합니다. 사용되는 serializer에 따라 동일한 형식이 XML로 다르게 직렬화될 수 있습니다. 실수로 잘못된 serializer를 사용하는 경우 공개할 의도가 없는 형식의 정보를 공개할 수 있습니다.

예를 들어, DataContractSerializer 클래스는 데이터 계약 형식을 직렬화할 때 DataMemberAttribute 특성으로 표시된 멤버만 직렬화합니다. XmlSerializer 클래스는 모든 공용 멤버를 직렬화합니다. 다음 코드의 형식을 참조하세요.

[DataContract]
public class Customer
{
    [DataMember]
    public string firstName;
    [DataMember]
    public string lastName;
    public string creditCardNumber;
}
<DataContract()> _
Public Class Customer
    <DataMember()> _
    Public firstName As String
    <DataMember()> _
    Public lastName As String
    Public creditCardNumber As String
End Class

서비스 계약에서 XmlSerializer 클래스가 선택된 경우 creditCardNumber 형식이 실수로 사용되면 멤버가 직렬화됩니다. 이것은 아마도 의도된 것이 아닐 수 있습니다.

기본값이 DataContractSerializer 클래스이더라도, 서비스 계약 유형에 DataContractFormatAttribute 특성을 적용하여 이를 서비스에 대해 명시적으로 선택할 수 있습니다. 하지만 이러한 작업은 절대 필요하지 않습니다.

서비스에 사용되는 serializer는 계약의 필수적인 부분이며 다른 바인딩을 선택하거나 다른 구성 설정을 변경하여 변경할 수 없습니다.

다른 중요한 보안 고려 사항은 클래스에 XmlSerializer 적용됩니다. 첫째, 클래스를 사용하는 XmlSerializer 모든 WCF 애플리케이션은 공개로부터 보호되는 키로 서명하는 것이 좋습니다. 수동으로 XmlSerializer로 전환하거나 자동으로 전환될 때(Svcutil.exe, 서비스 참조 추가 또는 유사한 도구에 의해 이뤄질 때) 모두 이 권장 사항이 적용됩니다. 직렬화 엔진은 애플리케이션과 동일한 키로 서명된 한, 사전에 생성된 직렬화 어셈블리의 로드를 지원하기 때문입니다. 서명되지 않은 애플리케이션은 애플리케이션 폴더 또는 전역 어셈블리 캐시에 배치되는 미리 생성된 serialization 어셈블리의 예상 이름과 일치하는 악의적인 어셈블리의 가능성에서 완전히 보호되지 않습니다. 물론 공격자는 이 작업을 시도하려면 먼저 이러한 두 위치 중 하나에 대한 쓰기 액세스 권한을 얻어야 합니다.

사용할 XmlSerializer 때마다 존재하는 또 다른 위협은 시스템 임시 폴더에 대한 쓰기 액세스와 관련이 있습니다. serialization 엔진은 XmlSerializer 이 폴더에 임시 serialization 어셈블리를 만들고 사용합니다. 임시 폴더에 대한 쓰기 권한이 있는 모든 프로세스는 이러한 serialization 어셈블리를 악성 코드로 덮어쓸 수 있습니다.

XmlSerializer 지원에 대한 규칙

계약 작업 매개 변수 또는 반환 값에 호환되는 특성을 직접 적용 XmlSerializer할 수 없습니다. 그러나 다음 코드와 같이 형식화된 메시지(메시지 계약 본문 부분)에 적용할 수 있습니다.

[ServiceContract]
[XmlSerializerFormat]
public class BankingService
{
    [OperationContract]
    public void ProcessTransaction(BankingTransaction bt)
    {
        //Code not shown.
    }
}

[MessageContract]
public class BankingTransaction
{
    [MessageHeader]
    public string Operation;
    [XmlElement, MessageBodyMember]
    public Account fromAccount;
    [XmlElement, MessageBodyMember]
    public Account toAccount;
    [XmlAttribute, MessageBodyMember]
    public int amount;
}
<ServiceContract(), XmlSerializerFormat()> _
Public Class BankingService
    <OperationContract()> _
    Public Sub ProcessTransaction(ByVal bt As BankingTransaction)
        'Code not shown.
    End Sub
End Class

<MessageContract()> _
Public Class BankingTransaction
    <MessageHeader()> _
    Public Operation As String
    <XmlElement(), MessageBodyMember()> _
    Public fromAccount As Account
    <XmlElement(), MessageBodyMember()> _
    Public toAccount As Account
    <XmlAttribute(), MessageBodyMember()> _
    Public amount As Integer
End Class

형식화된 메시지 멤버에 적용되는 경우 이러한 특성은 형식화된 메시지 특성에서 충돌하는 속성을 재정의합니다. 예를 들어, 다음 코드에서 ElementNameName을 재정의합니다.

    [MessageContract]
    public class BankingTransaction
    {
        [MessageHeader] public string Operation;

        //This element will be <fromAcct> and not <from>:
        [XmlElement(ElementName="fromAcct"), MessageBodyMember(Name="from")]
        public Account fromAccount;

        [XmlElement, MessageBodyMember]
        public Account toAccount;

        [XmlAttribute, MessageBodyMember]
        public int amount;
}
<MessageContract()> _
Public Class BankingTransaction
    <MessageHeader()> _
    Public Operation As String

    'This element will be <fromAcct> and not <from>:
    <XmlElement(ElementName:="fromAcct"), _
        MessageBodyMember(Name:="from")> _
    Public fromAccount As Account

    <XmlElement(), MessageBodyMember()> _
    Public toAccount As Account

    <XmlAttribute(), MessageBodyMember()> _
    Public amount As Integer
End Class

MessageHeaderArrayAttribute를 사용할 때 XmlSerializer 특성은 지원되지 않습니다.

비고

이 경우, WCF 이전에 이미 존재했던 다음 예외가 XmlSerializer에 의해 throw됩니다: "스키마의 최상위 수준에서 선언된 요소는 maxOccurs> 1을 가질 수 없습니다." XmlArray 대신 XmlArrayItemXmlElementAttribute 또는 래핑된 매개 변수 스타일을 사용하여 'more'에 대한 래퍼 요소를 제공합니다.

이러한 예외가 발생하면 이 상황이 적용되는지 조사합니다.

WCF는 메시지 계약 및 작업 계약에서 SoapIncludeAttributeXmlIncludeAttribute 특성을 지원하지 않습니다. 대신 KnownTypeAttribute 특성을 사용하십시오.

IXmlSerializable 인터페이스를 구현하는 형식

인터페이스를 IXmlSerializable 구현하는 형식은 DataContractSerializer에 의해 완전히 지원됩니다. XmlSchemaProviderAttribute 해당 스키마를 제어하려면 항상 이러한 형식에 특성을 적용해야 합니다.

경고

다형 형식을 직렬화하는 경우, 올바른 형식이 직렬화되도록 XmlSchemaProviderAttribute을(를) 형식에 적용해야 합니다.

구현 IXmlSerializable하는 형식에는 임의의 콘텐츠를 나타내는 형식, 단일 요소를 나타내는 형식 및 레거시 형식의 세 가지 종류가 DataSet 있습니다.

  • 콘텐츠 형식은 특성에 지정된 스키마 공급자 메서드를 XmlSchemaProviderAttribute 사용합니다. 메서드는 null를 반환하지 않으며, 특성의 IsAny 속성은 기본값 false로 남아 있습니다. 'IXmlSerializable 형식'의 가장 일반적인 사용 방법입니다.

  • 요소 형식은 형식이 IXmlSerializable 고유한 루트 요소 이름을 제어해야 하는 경우에 사용됩니다. 형식을 요소 형식으로 표시하려면 IsAny 속성에 있는 XmlSchemaProviderAttribute 속성을 true로 설정하거나 스키마 공급자 메서드에서 null을 반환하세요. 스키마 공급자 메서드를 갖는 것은 요소 형식에 대한 선택 사항입니다. 이 경우 메서드 이름 null대신 지정할 XmlSchemaProviderAttribute 수 있습니다. 그러나 IsAnytrue이고 스키마 공급자 메서드가 지정된 경우, 그 메서드는 null를 반환해야 합니다.

  • 레거시 DataSet 유형은 IXmlSerializable 속성으로 표시되지 않는 XmlSchemaProviderAttribute 유형입니다. 대신 스키마 생성을 위한 메서드를 GetSchema 사용합니다. 이 패턴은 DataSet 형식에 사용되며, 형식화된 데이터 세트가 이전 버전의 .NET Framework에서는 클래스를 파생시켰습니다. 그러나 지금은 구식으로 여겨지며 레거시 시스템을 지원하기 위해서만 사용됩니다. 이 패턴에 의존하지 말고 항상 XmlSchemaProviderAttribute를 귀하의 IXmlSerializable 형식에 적용하십시오.

IXmlSerializable 콘텐츠 형식

특정 콘텐츠 형식인 형식의 데이터 멤버를 직렬화할 때는, 이전에 정의된 바와 같이 serializer가 데이터 멤버에 대한 래퍼 요소를 생성하고, IXmlSerializable 메서드에 제어를 넘깁니다. 구현은 WriteXml 래퍼 요소에 특성을 추가하는 것을 포함하는 XML을 작성할 수 있습니다. WriteXml 작업이 완료되면 serializer가 요소를 닫습니다.

데이터 멤버가 이전에 정의된 콘텐츠 형식을 구현하는 유형인 경우, 역직렬 변환기는 데이터 멤버의 래퍼 요소에 XML 판독기를 배치하고 IXmlSerializable 메서드로 제어를 전달합니다. 메서드는 시작 및 끝 태그를 포함하여 전체 요소를 읽어야 합니다. ReadXml 코드가 요소가 비어 있는 경우를 처리하는지 확인하십시오. 또한, 당신의 ReadXml 구현은 래퍼 요소가 특정한 방식으로 이름이 지어져야 한다는 것에 의존해서는 안 됩니다. 직렬 변환기에 의해 선택된 이름은 다양할 수 있습니다.

예를 들어 형식의 데이터 멤버에 콘텐츠 형식을 다형적으로 할당 IXmlSerializable 할 수 있습니다 Object. 형식 인스턴스가 null일 수도 있습니다. 마지막으로, IXmlSerializable 형식을 사용하면서 개체 그래프 보존을 활성화하고 NetDataContractSerializer와 함께 사용할 수 있습니다. 이러한 모든 기능을 사용하려면 WCF 직렬화기가 특정 특성을 래퍼 요소에 첨부해야 합니다. 이 특성은 XML 스키마 인스턴스 네임스페이스의 "nil" 및 "type" 그리고 WCF 전용 네임스페이스의 "Id", "Ref", "Type", "Assembly"입니다.

ReadXml을 구현할 때 무시할 특성

코드에 ReadXml 컨트롤을 전달하기 전에 디시리얼라이저는 XML 요소를 검사하여 이러한 특수 XML 특성을 검색하고, 해당 특성에 대해 처리합니다. 예를 들어 "nil" true이면 null 값이 역직렬화되고 ReadXml 호출되지 않습니다. 다형성이 감지되면 요소의 내용이 다른 형식인 것처럼 역직렬화됩니다. 다형적으로 할당된 형식의 구현 ReadXml 이 호출됩니다. 어떤 경우든 구현은 ReadXml 역직렬 변환기에 의해 처리되므로 이러한 특수 특성을 무시해야 합니다.

IXmlSerializable 콘텐츠 형식에 대한 스키마 고려 사항

스키마 및 콘텐츠 형식을 IXmlSerializable 내보낼 때 스키마 공급자 메서드가 호출됩니다. 스키마 공급자 메서드에 XmlSchemaSet가 전달됩니다. 메서드는 스키마 집합에 유효한 스키마를 추가할 수 있습니다. 스키마 집합에는 스키마 내보내기가 발생할 때 이미 알려진 스키마가 포함됩니다. 스키마 공급자 메서드가 스키마 집합에 항목을 추가해야 하는 경우 해당 네임스페이스가 있는 항목이 집합에 이미 있는지 확인해야 XmlSchema 합니다. 이 경우 스키마 공급자 메서드는 새 항목을 기존 XmlSchema항목에 추가해야 합니다. 그렇지 않으면 새 XmlSchema 인스턴스를 만들어야 합니다. 이는 형식 배열 IXmlSerializable 을 사용하는 경우에 중요합니다. 예를 들어 네임스페이스 "B"에서 "A" 형식으로 내보내지는 형식이 있는 경우 IXmlSerializable 스키마 공급자 메서드가 호출될 때까지 스키마 집합에 "ArrayOfA" 형식을 보유할 "B"에 대한 스키마가 이미 포함되어 있을 수 있습니다.

형식을 XmlSchemaSet추가하는 것 외에도 콘텐츠 형식에 대한 스키마 공급자 메서드는 null이 아닌 값을 반환해야 합니다. XmlQualifiedName 형식을 사용할 때 사용할 스키마 형식 이름을 지정하는 IXmlSerializable을(를) 반환할 수 있습니다. 이 정규화된 이름은 형식의 데이터 계약 이름 및 네임스페이스로도 사용됩니다. 스키마 공급자 메서드가 반환될 때 스키마 집합에 없는 형식을 즉시 반환할 수 있습니다. 그러나 모든 관련 형식을 내보낼 때까지(Export메서드가 모든 관련 형식에 대해 호출되고 XsdDataContractExporter 속성에 Schemas 액세스됨) 스키마 집합에 형식이 존재할 것으로 예상됩니다. 모든 관련 Schemas 호출이 이루어지기 전에 Export 속성에 액세스하면 XmlSchemaException이 발생할 수 있습니다. 내보내기 프로세스에 대한 자세한 내용은 클래스에서 스키마 내보내기를 참조하세요.

스키마 제공자 메서드는 사용할 XmlSchemaType를 반환할 수도 있습니다. 형식은 익명일 수도 있고, 익명에 해당하지 않을 수도 있습니다. 익명인 경우, IXmlSerializable 유형이 데이터 멤버로 사용될 때마다 IXmlSerializable 유형의 스키마가 익명 유형으로 내보내집니다. 형식에는 IXmlSerializable 여전히 데이터 계약 이름과 네임스페이스가 있습니다. (이 특성은 이름을 사용자 지정하는 데 사용할 수 없다는 점을 제외하고 DataContractAttribute에 설명된 대로 결정됩니다.) 익명이 아니면 .의 형식 XmlSchemaSet중 하나여야 합니다. 이 경우는 형식의 XmlQualifiedName을 반환하는 것과 같습니다.

또한 형식에 대해 전역 요소 선언을 내보냅니다. 형식에 XmlRootAttribute 특성이 적용되지 않은 경우, 요소의 이름과 네임스페이스는 데이터 계약과 동일하며, 해당 "nillable" 속성은 true입니다. 유일한 예외는 스키마 네임스페이스(http://www.w3.org/2001/XMLSchema)입니다. 형식의 데이터 계약이 이 네임스페이스에 있는 경우 스키마 네임스페이스에 새 요소를 추가할 수 없으므로 해당 전역 요소가 빈 네임스페이스에 있습니다. 형식에 XmlRootAttribute 특성이 적용된 경우, 전역 요소 선언은 ElementName, Namespace, IsNullable 속성을 사용하여 내보냅니다. 적용된 XmlRootAttribute 기본값은 데이터 계약 이름, 빈 네임스페이스 및 "nillable"입니다 true.

동일한 전역 요소 선언 규칙이 레거시 데이터 세트 형식에 적용됩니다. XmlRootAttribute는 스키마 공급자 메서드를 사용하여 XmlSchemaSet에 추가되거나, GetSchema 레거시 데이터 세트 형식에 대해 사용자 지정 코드를 통해 추가된 전역 요소 선언을 재정의할 수 없습니다.

IXmlSerializable 요소 형식

IXmlSerializable 요소 형식에는 속성이 IsAny로 설정되거나, 스키마 공급자 메서드가 true를 반환하는 경우가 있습니다.

요소 형식을 직렬화 및 역직렬화하는 것은 콘텐츠 형식을 직렬화 및 역직렬화하는 것과 매우 유사합니다. 그러나 몇 가지 중요한 차이점이 있습니다.

  • WriteXml 구현은 정확히 하나의 요소(물론 여러 자식 요소를 포함할 수 있음)를 구현해야 합니다. 이 단일 요소, 여러 형제 요소 또는 혼합 콘텐츠 외부에서 특성을 작성해서는 안 됩니다. 요소가 비어 있을 수 있습니다.

  • ReadXml 구현체는 래퍼 요소를 읽지 않아야 합니다. 하나의 요소를 WriteXml가 생성한 것으로 읽는 것이 기대됩니다.

  • 요소 형식을 정기적으로 직렬화할 때(예: 데이터 계약의 데이터 멤버) serializer는 콘텐츠 형식과 마찬가지로 호출 WriteXml하기 전에 래퍼 요소를 출력합니다. 그러나 최상위 수준에서 요소 형식을 직렬화할 때, 루트 이름과 네임스페이스가 WriteXml 또는 DataContractSerializer 생성자에서 직렬 변환기를 구성할 때 명시적으로 지정되지 않는다면 직렬 변환기는 일반적으로 NetDataContractSerializer에서 생성되는 요소 주위에 래퍼 요소를 출력하지 않습니다. 자세한 내용은 직렬화 및 역직렬화를 참조하세요.

  • 생성 시 루트 이름 및 네임스페이스를 지정하지 않고 최상위 수준에서 요소 형식을 serialize할 경우, WriteStartObjectWriteEndObject은 본질적으로 아무 작업도 하지 않고, WriteObjectContentWriteXml를 호출합니다. 이 모드에서는 직렬화되는 개체가 null이 될 수 없으며, 다형적으로 할당할 수 없습니다. 또한 개체 그래프 보존은 활성화할 수 없으며 NetDataContractSerializer는 사용할 수 없습니다.

  • 생성 시 IsStartObject 루트 이름과 네임스페이스를 지정하지 않고 최상위 수준에서 요소 형식을 역직렬화하는 경우 요소의 시작을 찾을 수 있는지 반환 true 합니다. ReadObjectverifyObjectName로 설정된 true 매개 변수를 사용하여 실질적으로 개체를 읽기 전에 IsStartObject와 동일한 방식으로 동작합니다. ReadObject 그런 다음 메서드에 컨트롤을 ReadXml 전달합니다.

요소 형식에 대해 내보낸 스키마는 이전 섹션에서 설명한 XmlElement 형식과 동일하지만, 스키마 공급자 메서드가 콘텐츠 형식처럼 XmlSchemaSet에 추가적인 스키마를 더할 수 있다는 점이 다릅니다. 요소 형식에 XmlRootAttribute 특성을 사용할 수 없으며 이러한 형식에 대해 전역 요소 선언은 내보내지지 않습니다.

XmlSerializer와 차이점

IXmlSerializableXmlSchemaProviderAttribute 인터페이스 및 XmlRootAttributeXmlSerializer 특성을 이해합니다. 그러나 데이터 계약 모델에서 이러한 항목이 처리되는 방식에는 몇 가지 차이점이 있습니다. 중요한 차이점은 다음 목록에 요약되어 있습니다.

  • 스키마 공급자 메서드는 공용이어야 합니다. 그러나 데이터 계약 모델에서 XmlSerializer사용하려면 public일 필요는 없습니다.

  • 스키마 공급자 메서드는 IsAnytrue 데이터 계약 모델에 있을 때 호출되지만, XmlSerializer와 함께 있지는 않습니다.

  • 콘텐츠 또는 레거시 데이터 세트 형식에 대해 XmlRootAttribute 특성이 없으면, XmlSerializer가 빈 네임스페이스에서 전역 요소 선언을 내보냅니다. 데이터 계약 모델에서 사용되는 네임스페이스는 일반적으로 앞에서 설명한 대로 데이터 계약 네임스페이스입니다.

두 serialization 기술에 모두 사용되는 형식을 만들 때는 이러한 차이점에 유의하세요.

IXmlSerializable 스키마 가져오기

형식의 IXmlSerializable로 생성된 스키마를 가져올 때 몇 가지 가능성이 있습니다.

  • 생성된 스키마는 데이터 계약 스키마 참조에 설명된 대로 유효한 데이터 계약 스키마일 수 있습니다. 이 경우 스키마를 평소와 같이 가져올 수 있으며 일반 데이터 계약 형식이 생성됩니다.

  • 생성된 스키마가 유효한 데이터 계약 스키마가 아닐 수 있습니다. 예를 들어 스키마 공급자 메서드는 데이터 계약 모델에서 지원되지 않는 XML 특성을 포함하는 스키마를 생성할 수 있습니다. 이 경우 IXmlSerializable 형식으로 스키마를 가져올 수 있습니다. 이 가져오기 모드는 기본적으로 설정되어 있지 않지만 쉽게 사용하도록 설정할 수 있습니다. 예를 들어 /importXmlTypes 명령줄이 ServiceModel 메타데이터 유틸리티 도구(Svcutil.exe)로 전환됩니다. 클래스 를 생성하기 위한 스키마 가져오기에 자세히 설명되어 있습니다. 형식 인스턴스에 대한 XML로 직접 작업해야 합니다. 더 넓은 범위의 스키마를 지원하는 다른 직렬화 기술을 사용하는 것도 고려할 수 있습니다. 사용 XmlSerializer방법에 대한 항목을 참조하세요.

  • 새 형식을 생성하는 대신 프록시에서 기존 IXmlSerializable 형식을 다시 사용할 수 있습니다. 이 경우 형식 생성 항목으로 스키마 가져오기 항목에 설명된 참조된 형식 기능을 사용하여 다시 사용할 형식을 나타낼 수 있습니다. 이것은 다시 사용할 형식을 포함하는 어셈블리를 지정하는 svcutil.exe에서 /reference 스위치를 사용하는 것과 같습니다.

XmlSerializer 레거시 동작

.NET Framework 4.0 이하에서 XmlSerializer는 C# 코드를 파일에 작성하여 임시 serialization 어셈블리를 생성했습니다. 그런 다음 파일이 어셈블리로 컴파일되었습니다. 이 동작은 serializer의 시작 시간을 늦추는 것과 같은 바람직하지 않은 결과를 가져왔습니다. .NET Framework 4.5에서는 컴파일러를 사용하지 않고 어셈블리를 생성하도록 이 동작이 변경되었습니다. 일부 개발자는 생성된 C# 코드를 보려고 할 수 있습니다. 다음 구성으로 이 레거시 동작을 사용하도록 지정할 수 있습니다.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.xml.serialization>
    <xmlSerializer tempFilesLocation='e:\temp\XmlSerializerBug' useLegacySerializerGeneration="true" />
  </system.xml.serialization>
  <system.diagnostics>
    <switches>
      <add name="XmlSerialization.Compilation" value="1" />
    </switches>
  </system.diagnostics>
</configuration>

호환성 문제로 인해 공용이 아닌 새 재정의 XmlSerializer 를 사용하여 파생 클래스를 직렬화하지 못하는 경우, 다음 구성을 사용하여 XMLSerializer 기존 방식으로 다시 전환할 수 있습니다.

<configuration>
  <appSettings>
    <add key="System:Xml:Serialization:UseLegacySerializerGeneration" value="true" />
  </appSettings>
</configuration>

위의 구성 대신 .NET Framework 4.5 이상 버전을 실행하는 컴퓨터에서 다음 구성을 사용할 수 있습니다.

<configuration>
  <system.xml.serialization>
    <xmlSerializer useLegacySerializerGeneration="true"/>
  </system.xml.serialization>
</configuration>

비고

스위치는 <xmlSerializer useLegacySerializerGeneration="true"/> .NET Framework 4.5 이상 버전을 실행하는 컴퓨터에서만 작동합니다. 위의 appSettings 방법은 모든 .NET Framework 버전에서 작동합니다.

참고하십시오