Freigeben über


Bekannte Typen

Das KnownTypes-Beispiel veranschaulicht, wie Informationen zu abgeleiteten Typen in einem Datenvertrag angegeben werden. Mit Datenverträgen können Sie strukturierte Daten an und von Diensten weitergeben. Bei der objektorientierten Programmierung kann ein Typ, der von einem anderen Typ erbt, anstelle des ursprünglichen Typs verwendet werden. Bei der dienstorientierten Programmierung werden Schemas statt Typen kommuniziert und daher wird die Beziehung zwischen Typen nicht beibehalten. Das KnownTypeAttribute Attribut ermöglicht die Aufnahme von Informationen zu abgeleiteten Typen in den Datenvertrag. Wenn dieser Mechanismus nicht verwendet wird, kann kein abgeleiteter Typ gesendet oder empfangen werden, wenn ein Basistyp erwartet wird.

Hinweis

Die Einrichtungsverfahren und Build-Anweisungen für dieses Beispiel befinden sich am Ende dieses Themas.

Der Dienstvertrag für den Dienst verwendet komplexe Zahlen, wie im folgenden Beispielcode dargestellt.

// Define a service contract.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    ComplexNumber Add(ComplexNumber n1, ComplexNumber n2);
    [OperationContract]
    ComplexNumber Subtract(ComplexNumber n1, ComplexNumber n2);
    [OperationContract]
    ComplexNumber Multiply(ComplexNumber n1, ComplexNumber n2);
    [OperationContract]
    ComplexNumber Divide(ComplexNumber n1, ComplexNumber n2);
}

Die DataContractAttribute Klasse und DataMemberAttribute wird auf die ComplexNumber Klasse angewendet, um anzugeben, welche Felder der Klasse zwischen dem Client und dem Dienst übergeben werden können. Die Klasse ComplexNumberWithMagnitude, die abgeleitet ist, kann anstelle von ComplexNumber verwendet werden. Das KnownTypeAttribute Attribut für den ComplexNumber Typ gibt dies an.

[DataContract(Namespace="http://Microsoft.ServiceModel.Samples")]
[KnownType(typeof(ComplexNumberWithMagnitude))]
public class ComplexNumber
{
    [DataMember]
    public double Real = 0.0D;
    [DataMember]
    public double Imaginary = 0.0D;

    public ComplexNumber(double real, double imaginary)
    {
        this.Real = real;
        this.Imaginary = imaginary;
    }
}

Der ComplexNumberWithMagnitude-Typ leitet sich von ComplexNumber ab, enthält jedoch ein zusätzliches Datenmitglied Magnitude.

[DataContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public class ComplexNumberWithMagnitude : ComplexNumber
{
    public ComplexNumberWithMagnitude(double real, double imaginary) :
        base(real, imaginary) { }

    [DataMember]
    public double Magnitude
    {
        get { return Math.Sqrt(Imaginary*Imaginary  + Real*Real); }
        set { throw new NotImplementedException(); }
    }
}

Um die Funktion für bekannte Typen zu veranschaulichen, wird der Dienst so implementiert, dass er nur bei Addition und Subtraktion ein ComplexNumberWithMagnitude zurückgibt. (Obwohl der Vertrag angibt ComplexNumber, ist dies aufgrund des KnownTypeAttribute Attributs zulässig). Multiplikation und Division geben weiterhin den Basistyp ComplexNumber zurück.

public class DataContractCalculatorService : IDataContractCalculator
{
    public ComplexNumber Add(ComplexNumber n1, ComplexNumber n2)
    {
        //Return the derived type.
        return new ComplexNumberWithMagnitude(n1.Real + n2.Real,
                                      n1.Imaginary + n2.Imaginary);
    }

    public ComplexNumber Subtract(ComplexNumber n1, ComplexNumber n2)
    {
        //Return the derived type.
        return new ComplexNumberWithMagnitude(n1.Real - n2.Real,
                                 n1.Imaginary - n2.Imaginary);
    }

    public ComplexNumber Multiply(ComplexNumber n1, ComplexNumber n2)
    {
        double real1 = n1.Real * n2.Real;
        double imaginary1 = n1.Real * n2.Imaginary;
        double imaginary2 = n2.Real * n1.Imaginary;
        double real2 = n1.Imaginary * n2.Imaginary * -1;
        //Return the base type.
        return new ComplexNumber(real1 + real2, imaginary1 +
                                                  imaginary2);
    }

    public ComplexNumber Divide(ComplexNumber n1, ComplexNumber n2)
    {
        ComplexNumber conjugate = new ComplexNumber(n2.Real,
                                     -1*n2.Imaginary);
        ComplexNumber numerator = Multiply(n1, conjugate);
        ComplexNumber denominator = Multiply(n2, conjugate);
        //Return the base type.
        return new ComplexNumber(numerator.Real / denominator.Real,
                                             numerator.Imaginary);
    }
}

Auf dem Client werden sowohl der Dienstvertrag als auch der Datenvertrag in der Quelldatei generatedClient.cs definiert, die vom ServiceModel Metadata Utility Tool (Svcutil.exe) aus Dienstmetadaten generiert wird. Da das KnownTypeAttribute Attribut im Datenvertrag des Diensts angegeben ist, kann der Client sowohl die Klassen ComplexNumber als auch die ComplexNumberWithMagnitude Klassen empfangen, wenn er den Dienst verwendet. Der Client erkennt, ob er eine ComplexNumberWithMagnitude erhalten hat und die entsprechende Ausgabe generiert:

// Create a client
DataContractCalculatorClient client =
    new DataContractCalculatorClient();

// Call the Add service operation.
ComplexNumber value1 = new ComplexNumber() { real = 1, imaginary = 2 };
ComplexNumber value2 = new ComplexNumber() { real = 3, imaginary = 4 };
ComplexNumber result = client.Add(value1, value2);
Console.WriteLine("Add({0} + {1}i, {2} + {3}i) = {4} + {5}i",
    value1.real, value1.imaginary, value2.real, value2.imaginary,
    result.real, result.imaginary);
if (result is ComplexNumberWithMagnitude)
{
    Console.WriteLine("Magnitude: {0}",
        ((ComplexNumberWithMagnitude)result).Magnitude);
}
else
{
    Console.WriteLine("No magnitude was sent from the service");
}

Wenn Sie das Beispiel ausführen, werden die Anforderungen und Antworten des Vorgangs im Clientkonsolenfenster angezeigt. Beachten Sie, dass eine Größe für Addition und Subtraktion gedruckt wird, aber nicht für Multiplikation und Division wegen der Implementierung des Dienstes. Drücken Sie im Clientfenster die EINGABETASTE, um den Client zu schließen.

Add(1 + 2i, 3 + 4i) = 4 + 6i
Magnitude: 7.21110255092798
Subtract(1 + 2i, 3 + 4i) = -2 + -2i
Magnitude: 2.82842712474619
Multiply(2 + 3i, 4 + 7i) = -13 + 26i
No magnitude was sent from the service
Divide(3 + 7i, 5 + -2i) = 0.0344827586206897 + 41i
No magnitude was sent from the service

    Press <ENTER> to terminate client.

So können Sie das Beispiel einrichten, erstellen und ausführen

  1. Stellen Sie sicher, dass Sie das One-Time Setup-Verfahren für die Windows Communication Foundation-Beispieleausgeführt haben.

  2. Um die C#- oder Visual Basic .NET-Edition der Lösung zu erstellen, befolgen Sie die Anweisungen in Building the Windows Communication Foundation Samples.

  3. Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.