Partager via


Known Types

L’exemple KnownTypes montre comment spécifier des informations sur les types dérivés d’un contrat de données. Les contrats de données vous permettent de transférer des données structurées vers des services et à partir de ceux-ci. Dans la programmation orientée objet, un type qui hérite d'un autre peut être utilisé à la place de celui d'origine. Dans la programmation orientée service, ce sont les schémas et non pas les types qui sont communiqués et par conséquent, la relation entre les types n'est pas conservée. L'attribut KnownTypeAttribute permet d'inclure les informations sur les types dérivés dans le contrat de données. Si ce mécanisme n'est pas utilisé, un type dérivé ne peut pas être envoyé ou reçu là où un type de base est attendu.

Notes

La procédure d'installation ainsi que les instructions de génération relatives à cet exemple figurent à la fin de cette rubrique.

Le contrat de service du service utilise des nombres complexes, tel qu'indiqué dans l'exemple de code suivant.

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

DataContractAttribute et DataMemberAttribute sont appliqués à la classe ComplexNumber pour indiquer les champs de la classe qui peuvent être passés entre le client et le service. Vous pouvez utiliser la classe dérivée ComplexNumberWithMagnitude à la place de ComplexNumber. L'attribut KnownTypeAttribute sur le type ComplexNumber indique cela.

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

Le type ComplexNumberWithMagnitude dérive de ComplexNumber mais ajoute un membre de données supplémentaire, 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(); }
    }
}

Pour présenter la fonctionnalité des types connus, le service est implémenté de manière à retourne un ComplexNumberWithMagnitude pour l’addition et la soustraction uniquement. (Même si le contrat spécifie ComplexNumber, cela est autorisé en raison de l'attribut KnownTypeAttribute). La multiplication et la division retournent toujours le type de base ComplexNumber.

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

Sur le client, le contrat de service et le contrat de données sont tous deux définis dans le fichier source generatedClient.cs, qui est généré par l’outil ServiceModel Metadata Utility Tool (Svcutil.exe) à partir des métadonnées de service. L'attribut KnownTypeAttribute étant spécifié dans le contrat de données du service, le client peut recevoir à la fois les classes ComplexNumber et ComplexNumberWithMagnitude lors de l'utilisation du service. Le client détecte s'il a obtenu un ComplexNumberWithMagnitude et génère la sortie appropriée :

// 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");
}

Lorsque vous exécutez l'exemple, les demandes et réponses de l'opération s'affichent dans la fenêtre de console du client. Notez qu'une magnitude est imprimée pour l'addition et la soustraction, mais pas pour la multiplication et la division en raison de la façon dont le service a été implémenté. Appuyez sur Entrée dans la fenêtre du client pour l'arrêter.

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.

Pour configurer, générer et exécuter l'exemple

  1. Assurez-vous d’avoir effectué la Procédure d’installation unique pour les exemples Windows Communication Foundation.

  2. Pour générer l’édition C# ou Visual Basic .NET de la solution, conformez-vous aux instructions figurant dans Building the Windows Communication Foundation Samples.

  3. Pour exécuter l’échantillon dans une configuration à un ou plusieurs ordinateurs, conformez-vous aux instructions fournies dans Exécution des échantillons Windows Communication Foundation.