Partager via


Known Types

Cet exemple 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 passer des données structurées à et depuis des services. 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.

ms751512.note(fr-fr,VS.100).gifRemarque :
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, les contrats de service et de données sont tous deux définis dans le fichier source generatedClient.cs, lequel est généré par Outil Service Model Metadata 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(); value1.real = 1; value1.imaginary = 2;
ComplexNumber value2 = new ComplexNumber(); value2.real = 3; value2.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 ENTER 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 indiquée à la section 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, suivez les instructions indiquées dans Génération des exemples Windows Communication Foundation.

  3. Pour exécuter l'exemple dans une configuration à un ou plusieurs ordinateurs, conformez-vous aux instructions figurant dans la rubrique Running the Windows Communication Foundation Samples.

ms751512.Important(fr-fr,VS.100).gif Remarque :
Les exemples peuvent déjà être installés sur votre ordinateur. Recherchez le répertoire (par défaut) suivant avant de continuer.

<LecteurInstall>:\WF_WCF_Samples

Si ce répertoire n'existe pas, rendez-vous sur la page (éventuellement en anglais) des exemples Windows Communication Foundation (WCF) et Windows Workflow Foundation (WF) pour .NET Framework 4 pour télécharger tous les exemples Windows Communication Foundation (WCF) et WF. Cet exemple se trouve dans le répertoire suivant.

<LecteurInstall>:\WF_WCF_Samples\WCF\Basic\Contract\Data\KnownTypes