Partager via


Types connus

L’exemple KnownTypes montre comment spécifier des informations sur les types dérivés dans un contrat de données. Les contrats de données vous permettent de transmettre des données structurées vers et depuis des services. Dans la programmation orientée objet, un type qui hérite d’un autre type peut être utilisé à la place du type d’origine. Dans la programmation orientée service, les schémas plutôt que les types sont communiqués et, par conséquent, la relation entre les types n’est pas conservée. L’attribut KnownTypeAttribute permet d’inclure des 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 où un type de base est attendu.

Remarque

La procédure d’installation et les instructions de génération de cet exemple se trouvent à la fin de cette rubrique.

Le contrat de service pour le service utilise des nombres complexes, comme 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);
}

Les 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. La classe dérivée ComplexNumberWithMagnitude peut être utilisée à la place de ComplexNumber. L’attribut KnownTypeAttribute sur le ComplexNumber type 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 ComplexNumberWithMagnitude type 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 illustrer la fonctionnalité de types connus, le service est implémenté de telle sorte qu’il retourne un ComplexNumberWithMagnitude uniquement pour l'addition et la soustraction. (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 définis dans le fichier source generatedClient.cs, qui est généré par l’outil utilitaire de métadonnées ServiceModel (Svcutil.exe) à partir des métadonnées du service. Étant donné que l’attribut KnownTypeAttribute est 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 requêtes et les réponses de l’opération s’affichent dans la fenêtre de console cliente. 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 arrêter le client.

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’exemple dans une configuration à un ou plusieurs ordinateurs, conformez-vous aux instructions figurant dans la rubrique Exécution des exemples Windows Communication Foundation.