IDataContractSurrogate Schnittstelle

Definition

Stellt die erforderlichen Methoden bereit, um mithilfe des DataContractSerializer bei der Serialisierung, der Deserialisierung und beim Export und Import von XSD (XML Schema Documents) einen Typen durch einen anderen zu ersetzen.

public interface class IDataContractSurrogate
public interface IDataContractSurrogate
type IDataContractSurrogate = interface
Public Interface IDataContractSurrogate

Beispiele

Im folgenden Beispiel wird eine Implementierung der IDataContractSurrogate-Schnittstelle veranschaulicht. Der Code ersetzt die Serialisierung des Person Typs durch eine PersonSurrogated-Klasse.


class program
{
    static void Main(string[] args)
    {
        SerializeWithSurrogate("surrogateEmployee.xml");
        DeserializeSurrogate("surrogateEmployee.xml");
        // Create an XmlSchemaSet to hold schemas from the
        // schema exporter.
        //XmlSchemaSet schemas = new XmlSchemaSet();
        //ExportSchemas("surrogateEmployee.xml", ref schemas);
        //// Pass the schemas to the importer.
        //ImportSchemas(schemas);
    }

    static  DataContractSerializer CreateSurrogateSerializer()
    {
        // Create an instance of the DataContractSerializer. The
        // constructor demands a knownTypes and surrogate.
        // Create a Generic List for the knownTypes.
        List<Type> knownTypes = new List<Type>();
        LegacyPersonTypeSurrogate surrogate = new LegacyPersonTypeSurrogate ();
        DataContractSerializer surrogateSerializer =
            new DataContractSerializer(typeof(Employee),
           knownTypes, Int16.MaxValue, false, true, surrogate);
        return surrogateSerializer;
    }

    static void SerializeWithSurrogate(string filename )
    {
        // Create and populate an Employee instance.
        Employee emp = new Employee();
        emp.date_hired = new DateTime(1999, 10, 14);
        emp.salary = 33000;

        // Note that the Person class is a legacy XmlSerializable class
        // without a DataContract.
        emp.person = new Person();
        emp.person.first_name = "Mike";
        emp.person.last_name = "Ray";
        emp.person.age = 44;

        // Create a new writer. Then serialize with the
        // surrogate serializer.
        FileStream  fs =new FileStream(filename, FileMode.Create);
        DataContractSerializer surrogateSerializer = CreateSurrogateSerializer();
        try{
            surrogateSerializer.WriteObject(fs, emp);
            Console.WriteLine("Serialization succeeded. ");
            fs.Close();
        }
        catch (SerializationException exc )
            {
            Console.WriteLine(exc.Message);
            }
    }

    static void DeserializeSurrogate( string filename )
    {
        // Create a new reader object.
        FileStream fs2 = new FileStream(filename, FileMode.Open);
        XmlDictionaryReader reader =
            XmlDictionaryReader.CreateTextReader(fs2, new XmlDictionaryReaderQuotas());

        Console.WriteLine("Trying to deserialize with surrogate.");
        try
        {
            DataContractSerializer surrogateSerializer = CreateSurrogateSerializer();
            Employee newemp = (Employee) surrogateSerializer.ReadObject(reader, false);

            reader.Close();
            fs2.Close();

            Console.WriteLine("Deserialization succeeded. \n\n");
            Console.WriteLine("Deserialized Person data: \n\t {0} {1}",
                    newemp.person.first_name, newemp.person.last_name);
                Console.WriteLine("\t Age: {0} \n", newemp.person.age);
            Console.WriteLine("\t Date Hired: {0}", newemp.date_hired.ToShortDateString());
            Console.WriteLine("\t Salary: {0}", newemp.salary);
            Console.WriteLine("Press Enter to end or continue");
            Console.ReadLine();
        }
        catch (SerializationException serEx  )
        {
            Console.WriteLine(serEx.Message);
            Console.WriteLine(serEx.StackTrace);
        }
    }

    static void ExportSchemas(string filename , ref XmlSchemaSet schemas)
{
        Console.WriteLine("Now doing schema export.");
        // The following code demonstrates schema export with a surrogate.
        // The surrogate indicates how to export the non-DataContract Person type.
        // Without the surrogate, schema export would fail.
        XsdDataContractExporter xsdexp = new XsdDataContractExporter();
        xsdexp.Options = new ExportOptions();
        xsdexp.Options.DataContractSurrogate = new LegacyPersonTypeSurrogate();
        xsdexp.Export(typeof(Employee));

        // Write out the exported schema to a file.
        using (FileStream fs3 = new FileStream("sample.xsd", FileMode.Create))
        {
            foreach (XmlSchema sch in xsdexp.Schemas.Schemas())
            {
                sch.Write(fs3);
            }
        }
    }

    static void ImportSchemas(XmlSchemaSet schemas ){
        Console.WriteLine("Now doing schema import.");
        // The following code demonstrates schema import with
        // a surrogate. The surrogate is used to indicate that
        // the Person class already exists and that there is no
        // need to generate a new class when importing the
        // PersonSurrogated data contract. If the surrogate
        // was not used, schema import would generate a
        // PersonSurrogated class, and the person field
        // of Employee would be imported as
        // PersonSurrogated and not Person.
        XsdDataContractImporter xsdimp = new XsdDataContractImporter();
        xsdimp.Options = new ImportOptions();
        xsdimp.Options.DataContractSurrogate = new LegacyPersonTypeSurrogate();
        xsdimp.Import(schemas);

        // Write out the imported schema to a C-Sharp file.
        // The code contains data contract types.
        FileStream fs4 = new FileStream("sample.cs", FileMode.Create);
        try
        {
            StreamWriter tw = new StreamWriter(fs4);
            Microsoft.CSharp.CSharpCodeProvider cdp = new Microsoft.CSharp.CSharpCodeProvider();
            cdp.GenerateCodeFromCompileUnit(xsdimp.CodeCompileUnit, tw, null);
            tw.Flush();
        }
        finally
        {
            fs4.Dispose();
        }

        Console.WriteLine( "\t  To see the results of schema export and import,");
        Console.WriteLine(" see SAMPLE.XSD and SAMPLE.CS." );

        Console.WriteLine(" Press ENTER to terminate the sample." );
        Console.ReadLine();
    }
}

// This is the Employee (outer) type used in the sample.

[DataContract()]
public class Employee
{
    [DataMember()]
    public DateTime date_hired ;

    [DataMember()]
public decimal salary ;

    [DataMember()]
    public Person person;
}

// This is the Person (inner) type used in the sample.
// Note that it is a legacy XmlSerializable type and not a DataContract type.

public class Person
{
    [XmlElement("FirstName")]
    public string first_name ;

    [XmlElement("LastName")]
    public string last_name ;

    [XmlAttribute("Age")]
    public Int16 age ;

    public Person()  {}
}

// This is the surrogated version of the Person type
// that will be used for its serialization/deserialization.

[DataContract] class PersonSurrogated
{
    // xmlData will store the XML returned for a Person instance
    // by the XmlSerializer.
    [DataMember()]
    public string xmlData;
}

 //This is the surrogate that substitutes PersonSurrogated for Person.
public class LegacyPersonTypeSurrogate:IDataContractSurrogate
{
    public Type GetDataContractType(Type type)
{
        Console.WriteLine("GetDataContractType invoked");
        Console.WriteLine("\t type name: {0}", type.Name);
        // "Person" will be serialized as "PersonSurrogated"
        // This method is called during serialization,
        // deserialization, and schema export.
        if (typeof(Person).IsAssignableFrom(type))
{
Console.WriteLine("\t returning PersonSurrogated");
            return typeof(PersonSurrogated);
        }
        return type;
    }

public object GetObjectToSerialize(object obj, Type targetType)
{
        Console.WriteLine("GetObjectToSerialize Invoked");
        Console.WriteLine("\t type name: {0}", obj.ToString());
        Console.WriteLine("\t target type: {0}", targetType.Name);
        // This method is called on serialization.
        // If Person is not being serialized...
        if (obj is Person )
        {
            Console.WriteLine("\t returning PersonSurrogated");
            // ... use the XmlSerializer to perform the actual serialization.
            PersonSurrogated  ps = new PersonSurrogated();
            XmlSerializer xs = new XmlSerializer(typeof(Person));
            StringWriter sw = new StringWriter();
            xs.Serialize(sw, (Person)obj );
            ps.xmlData = sw.ToString();
            return ps;
        }
        return obj;
    }

    public object GetDeserializedObject(Object obj , Type targetType)
    {
        Console.WriteLine("GetDeserializedObject invoked");
        // This method is called on deserialization.
        // If PersonSurrogated is being deserialized...
        if (obj is PersonSurrogated)
            {
                //... use the XmlSerializer to do the actual deserialization.
                PersonSurrogated ps = (PersonSurrogated)obj;
                XmlSerializer xs = new XmlSerializer(typeof(Person));
                return (Person)xs.Deserialize(new StringReader(ps.xmlData));
            }
            return obj;
    }

    public Type GetReferencedTypeOnImport(string typeName,
        string typeNamespace, object customData)
    {
        Console.WriteLine("GetReferencedTypeOnImport invoked");
        // This method is called on schema import.
        // If a PersonSurrogated data contract is
        // in the specified namespace, do not create a new type for it
        // because there is already an existing type, "Person".
        Console.WriteLine( "\t Type Name: {0}", typeName);

        if (typeName.Equals("PersonSurrogated") )
        {
            Console.WriteLine("Returning Person");
            return typeof(Person);
        }
        return null;
    }

    public System.CodeDom.CodeTypeDeclaration ProcessImportedType(
        System.CodeDom.CodeTypeDeclaration typeDeclaration,
        System.CodeDom.CodeCompileUnit compileUnit)
    {
        // Console.WriteLine("ProcessImportedType invoked")
        // Not used in this sample.
        // You could use this method to construct an entirely new CLR
        // type when a certain type is imported, or modify a
        // generated type in some way.
        return typeDeclaration;
    }

        public object GetCustomDataToExport(Type clrType, Type dataContractType)
        {
            // Not used in this sample
            return null;
        }

        public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
        {
            // Not used in this sample
            return null;
        }

        public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
        {
            // Not used in this sample
        }
}
Class Program

    Public Shared Sub Main(ByVal args() As String)

        SerializeWithSurrogate("surrogateEmployee.xml")
        DeserializeSurrogate("surrogateEmployee.xml")
        ' Create an XmlSchemaSet to hold schemas from the
        ' schema exporter. 
        'Dim schemas As New XmlSchemaSet
        'ExportSchemas("surrogateEmployee.xml", schemas)
        ' Pass the schemas to the importer.
        'ImportSchemas(schemas)

    End Sub


    Shared Function CreateSurrogateSerializer() As DataContractSerializer
        ' Create an instance of the DataContractSerializer. The 
        ' constructor demands a knownTypes and surrogate. 
        ' Create a Generic List for the knownTypes. 
        Dim knownTypes As List(Of Type) = New List(Of Type)()
        Dim surrogate As New LegacyPersonTypeSurrogate()
        Dim surrogateSerializer As New  _
        DataContractSerializer(GetType(Employee), _
           knownTypes, Integer.MaxValue, False, True, surrogate)
        Return surrogateSerializer
    End Function

    Shared Sub SerializeWithSurrogate(ByVal filename As String)
        ' Create and populate an Employee instance.
        Dim emp As New Employee()
        emp.date_hired = New DateTime(1999, 10, 14)
        emp.salary = 33000

        ' Note that the Person class is a legacy XmlSerializable class
        ' without a DataContract.
        emp.person = New Person()
        emp.person.first_name = "Mike"
        emp.person.last_name = "Ray"
        emp.person.age = 44

        ' Create a new writer. Then serialize with the 
        ' surrogate serializer.
        Dim fs As New FileStream(filename, FileMode.Create)
        Dim surrogateSerializer As DataContractSerializer = CreateSurrogateSerializer()
        Try
            surrogateSerializer.WriteObject(fs, emp)
            Console.WriteLine("Serialization succeeded. ")
            fs.Close()
        Catch exc As SerializationException

            Console.WriteLine(exc.Message)
        End Try
    End Sub

    Shared Sub DeserializeSurrogate(ByVal filename As String)

        ' Create a new reader object.
        Dim fs2 As New FileStream(filename, FileMode.Open)
        Dim reader As XmlDictionaryReader = _
            XmlDictionaryReader.CreateTextReader(fs2, New XmlDictionaryReaderQuotas())

        Console.WriteLine("Trying to deserialize with surrogate.")
        Try
            Dim surrogateSerializer As DataContractSerializer = CreateSurrogateSerializer()
            Dim newemp As Employee = CType _
                (surrogateSerializer.ReadObject(reader, False), Employee)

            reader.Close()
            fs2.Close()

            Console.WriteLine("Deserialization succeeded. " + vbLf + vbLf)
            Console.WriteLine("Deserialized Person data: " + vbLf + vbTab + _
                " {0} {1}", newemp.person.first_name, newemp.person.last_name)
            Console.WriteLine(vbTab + " Age: {0} " + vbLf, newemp.person.age)
            Console.WriteLine(vbTab & "Date Hired: {0}", newemp.date_hired.ToShortDateString())
            Console.WriteLine(vbTab & "Salary: {0}", newemp.salary)
            Console.WriteLine("Press Enter to end or continue")
            Console.ReadLine()
        Catch serEx As SerializationException
            Console.WriteLine(serEx.Message)
            Console.WriteLine(serEx.StackTrace)
        End Try
    End Sub

    Shared Sub ExportSchemas(ByVal filename As String, ByRef Schemas As XmlSchemaSet)
        Console.WriteLine("Now doing schema export.")
        ' The following code demonstrates schema export with a surrogate.
        ' The surrogate indicates how to export the non-DataContract Person type.
        ' Without the surrogate, schema export would fail.
        Dim xsdexp As New XsdDataContractExporter()
        xsdexp.Options = New ExportOptions()
        xsdexp.Options.DataContractSurrogate = New LegacyPersonTypeSurrogate()
        xsdexp.Export(GetType(Employee))

        ' Write out the exported schema to a file.
        Dim fs3 As New FileStream("sample.xsd", FileMode.Create)
        Try
            Dim sch As XmlSchema
            For Each sch In xsdexp.Schemas.Schemas()
                sch.Write(fs3)
            Next sch
            Schemas = xsdexp.Schemas
        Catch serEx As SerializationException
            Console.WriteLine("Message: {0}", serEx.Message)
            Console.WriteLine("Inner Text: {0}", serEx.InnerException)

        Finally
            fs3.Dispose()
        End Try
    End Sub

    Shared Sub ImportSchemas(ByVal schemas As XmlSchemaSet)
        Console.WriteLine("Now doing schema import.")
        ' The following code demonstrates schema import with 
        ' a surrogate. The surrogate is used to indicate that 
        ' the Person class already exists and that there is no 
        ' need to generate a new class when importing the
        ' PersonSurrogated data contract. If the surrogate 
        ' was not used, schema import would generate a 
        ' PersonSurrogated class, and the person field 
        ' of Employee would be imported as 
        ' PersonSurrogated and not Person.
        Dim xsdimp As New XsdDataContractImporter()
        xsdimp.Options = New ImportOptions()
        xsdimp.Options.DataContractSurrogate = New LegacyPersonTypeSurrogate()
        xsdimp.Import(schemas)

        ' Write out the imported schema to a C-Sharp file.
        ' The code contains data contract types.
        Dim fs4 As FileStream = New FileStream("sample.cs", FileMode.Create)
        Try
            Dim tw As New StreamWriter(fs4)
            Dim cdp As New Microsoft.CSharp.CSharpCodeProvider()
            cdp.GenerateCodeFromCompileUnit(xsdimp.CodeCompileUnit, tw, Nothing)
            tw.Flush()
        Finally
            fs4.Dispose()
        End Try

        Console.WriteLine(vbLf + " To see the results of schema export and import,")
        Console.WriteLine(" see SAMPLE.XSD and SAMPLE.CS." + vbLf)

        Console.WriteLine(" Press ENTER to terminate the sample." + vbLf)
        Console.ReadLine()
    End Sub


End Class


' This is the Employee (outer) type used in the sample.

<DataContract()> Class Employee
    <DataMember()> _
    Public date_hired As DateTime

    <DataMember()> _
    Public salary As [Decimal]

    <DataMember()> _
    Public person As Person
End Class


' This is the Person (inner) type used in the sample.
' Note that it is a legacy XmlSerializable type and not a DataContract type.

Public Class Person
    <XmlElement("FirstName")> _
    Public first_name As String

    <XmlElement("LastName")> _
    Public last_name As String

    <XmlAttribute("Age")> _
    Public age As Integer


    Public Sub New()

    End Sub
End Class

' This is the surrogated version of the Person type
' that will be used for its serialization/deserialization.

<DataContract()> Class PersonSurrogated

    ' xmlData will store the XML returned for a Person instance 
    ' by the XmlSerializer.
    <DataMember()> _
    Public xmlData As String

End Class

' This is the surrogate that substitutes PersonSurrogated for Person.
Class LegacyPersonTypeSurrogate
    Implements IDataContractSurrogate

    Public Function GetDataContractType(ByVal type As Type) As Type _
       Implements IDataContractSurrogate.GetDataContractType
        Console.WriteLine("GetDataContractType invoked")
        Console.WriteLine(vbTab & "type name: {0}", type.Name)
        ' "Person" will be serialized as "PersonSurrogated"
        ' This method is called during serialization,
        ' deserialization, and schema export.
        If GetType(Person).IsAssignableFrom(type) Then
            Console.WriteLine(vbTab & "returning PersonSurrogated")
            Return GetType(PersonSurrogated)
        End If
        Return type

    End Function

    Public Function GetObjectToSerialize(ByVal obj As Object, _
        ByVal targetType As Type) As Object _
        Implements IDataContractSurrogate.GetObjectToSerialize
        Console.WriteLine("GetObjectToSerialize Invoked")
        Console.WriteLine(vbTab & "type name: {0}", obj.ToString)
        Console.WriteLine(vbTab & "target type: {0}", targetType.Name)
        ' This method is called on serialization.
        ' If Person is not being serialized...
        If TypeOf obj Is Person Then
            Console.WriteLine(vbTab & "returning PersonSurrogated")
            ' ... use the XmlSerializer to perform the actual serialization.
            Dim ps As New PersonSurrogated()
            Dim xs As New XmlSerializer(GetType(Person))
            Dim sw As New StringWriter()
            xs.Serialize(sw, CType(obj, Person))
            ps.xmlData = sw.ToString()
            Return ps
        End If
        Return obj

    End Function

    Public Function GetDeserializedObject(ByVal obj As Object, _
        ByVal targetType As Type) As Object Implements _
        IDataContractSurrogate.GetDeserializedObject
        Console.WriteLine("GetDeserializedObject invoked")
        ' This method is called on deserialization.
        ' If PersonSurrogated is being deserialized...
        If TypeOf obj Is PersonSurrogated Then
            Console.WriteLine(vbTab & "returning PersonSurrogated")
            '... use the XmlSerializer to do the actual deserialization.
            Dim ps As PersonSurrogated = CType(obj, PersonSurrogated)
            Dim xs As New XmlSerializer(GetType(Person))
            Return CType(xs.Deserialize(New StringReader(ps.xmlData)), Person)
        End If
        Return obj

    End Function

    Public Function GetReferencedTypeOnImport(ByVal typeName As String, _
        ByVal typeNamespace As String, ByVal customData As Object) As Type _
        Implements IDataContractSurrogate.GetReferencedTypeOnImport
        Console.WriteLine("GetReferencedTypeOnImport invoked")
        ' This method is called on schema import.
        ' If a PersonSurrogated data contract is 
        ' in the specified namespace, do not create a new type for it 
        ' because there is already an existing type, "Person".
        Console.WriteLine(vbTab & "Type Name: {0}", typeName)

        'If typeNamespace.Equals("http://schemas.datacontract.org/2004/07/DCSurrogateSample") Then
        If typeName.Equals("PersonSurrogated") Then
            Console.WriteLine("Returning Person")
            Return GetType(Person)
        End If
        'End If
        Return Nothing

    End Function

    Public Function ProcessImportedType(ByVal typeDeclaration _
        As System.CodeDom.CodeTypeDeclaration, _
        ByVal compileUnit As System.CodeDom.CodeCompileUnit) _
        As System.CodeDom.CodeTypeDeclaration _
        Implements IDataContractSurrogate.ProcessImportedType
        'Console.WriteLine("ProcessImportedType invoked")
        ' Not used in this sample.
        ' You could use this method to construct an entirely new CLR 
        ' type when a certain type is imported, or modify a 
        ' generated type in some way.
        Return typeDeclaration
    End Function


    Public Overloads Function GetCustomDataToExport _
        (ByVal clrType As Type, ByVal dataContractType As Type) As Object _
        Implements IDataContractSurrogate.GetCustomDataToExport
        ' Console.WriteLine("GetCustomDataToExport invoked")
        ' Not used in this sample
        Return Nothing
    End Function


    Public Overloads Function GetCustomDataToExport _
       (ByVal memberInfo As System.Reflection.MemberInfo, _
       ByVal dataContractType As Type) As Object _
        Implements IDataContractSurrogate.GetCustomDataToExport
        ' Console.WriteLine("GetCustomDataToExport invoked")
        ' Not used in this sample
        Return Nothing

    End Function


    Public Sub GetKnownCustomDataTypes(ByVal customDataTypes As Collection(Of Type)) _
 Implements IDataContractSurrogate.GetKnownCustomDataTypes
        Console.WriteLine("GetKnownCustomDataTypes invoked")
        ' Not used in this sample

    End Sub
End Class

Hinweise

Verwenden Sie den IDataContractSurrogate, wenn Sie den DataContractSerializer verwenden, falls Sie einen der folgenden Schritte ausführen möchten: einen Typ oder ein Objekt durch ein anderes ersetzen oder Schemavarianten dynamisch generieren. Eine Beispielanwendung finden Sie unter DataContract Surrogate. Weitere Informationen zu Datenverträgen finden Sie unter Verwenden von Datenverträgen.

Zur Laufzeit finden Sie den jeweiligen DataContractSerializer für jeden Vorgang in einem Dienst, indem Sie den OperationDescription verwenden, um die DataContractSerializerOperationBehavior-Instanz aufzufinden. Weitere Informationen zum Implementieren der Schnittstelle zum Erstellen eines Ersatzzeichens finden Sie unter Datenvertrags-Ersatzzeichen.

Sie können auch den IDataContractSurrogate verwenden, um den Import und Export von XML-Schemas zu beeinflussen, wenn Sie die XsdDataContractExporter -Klasse und die XsdDataContractImporter -Klasse verwenden. Dazu müssen Sie den IDataContractSurrogate der DataContractSurrogate-Eigenschaft der ExportOptions -Klasse oder der DataContractSurrogate-Eigenschaft der ImportOptions-Klasse zuweisen. Weitere Informationen finden Sie unter Schemaimport und -export.

Methoden

GetCustomDataToExport(MemberInfo, Type)

Fügt bei Schemaexportvorgängen für Rückgabewerte, die nicht NULL sind, Anmerkungen in das Schema ein.

GetCustomDataToExport(Type, Type)

Fügt bei Schemaexportvorgängen für Rückgabewerte, die nicht NULL sind, Anmerkungen in das Schema ein.

GetDataContractType(Type)

Gibt bei der Serialisierung, der Deserialisierung und beim Schemaimport- und -export einen Datenvertragstyp zurück, der den angegebenen Typ ersetzt.

GetDeserializedObject(Object, Type)

Gibt bei der Deserialisierung ein Objekt zurück, das ein Ersatz für das angegebene Objekt ist.

GetKnownCustomDataTypes(Collection<Type>)

Legt die Auflistung bekannter Typen fest, die für Serialisierung und Deserialisierung der benutzerdefinierten Datenobjekte verwendet werden soll.

GetObjectToSerialize(Object, Type)

Gibt bei der Serialisierung ein Objekt zurück, das das angegebene Objekt ersetzt.

GetReferencedTypeOnImport(String, String, Object)

Gibt während des Schemaimports den Typ zurück, auf den das Schema verweist.

ProcessImportedType(CodeTypeDeclaration, CodeCompileUnit)

Verarbeitet den Typ, der aus dem importierten Schema generiert wurde.

Gilt für:

Weitere Informationen