Condividi tramite


Tipi conosciuti

L'esempio KnownTypes illustra come specificare informazioni sui tipi derivati in un contratto dati. I contratti dati consentono di passare dati strutturati da e verso i servizi. Nella programmazione orientata agli oggetti, è possibile usare un tipo che eredita da un altro tipo al posto del tipo originale. Nella programmazione orientata ai servizi, gli schemi anziché i tipi vengono comunicati e pertanto la relazione tra i tipi non viene mantenuta. L'attributo KnownTypeAttribute consente di includere informazioni sui tipi derivati nel contratto dati. Se questo meccanismo non viene utilizzato, non è possibile inviare o ricevere un tipo derivato in cui è previsto un tipo di base.

Annotazioni

La procedura di installazione e le istruzioni di compilazione per questo esempio si trovano alla fine di questo argomento.

Il contratto di servizio per il servizio usa numeri complessi, come illustrato nel codice di esempio seguente.

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

Il DataContractAttribute e il DataMemberAttribute viene applicato alla classe ComplexNumber per indicare quali campi della classe possono essere passati tra il client e il servizio. La classe derivata ComplexNumberWithMagnitude può essere usata al posto di ComplexNumber. L'attributo KnownTypeAttribute sul ComplexNumber tipo indica questo.

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

Il ComplexNumberWithMagnitude tipo deriva da ComplexNumber ma aggiunge un membro dati aggiuntivo, 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(); }
    }
}

Per illustrare la funzionalità dei tipi noti, il servizio viene implementato in modo che restituisca un ComplexNumberWithMagnitude solo per addizione e sottrazione. Anche se il contratto specifica ComplexNumber, questo è consentito a causa dell'attributo KnownTypeAttribute . La moltiplicazione e la divisione restituiscono comunque il tipo di 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);
    }
}

Nel client, sia il contratto di servizio che il contratto dati vengono definiti nel file di origine generatedClient.cs, generato dallo strumento utilità metadati ServiceModel (Svcutil.exe) dai metadati del servizio. Poiché l'attributo KnownTypeAttribute viene specificato nel contratto dati del servizio, il client è in grado di ricevere entrambe le ComplexNumber classi e ComplexNumberWithMagnitude quando si usa il servizio. Il client rileva se ha ottenuto un ComplexNumberWithMagnitude e genera l'output appropriato:

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

Quando si esegue l'esempio, le richieste e le risposte dell'operazione vengono visualizzate nella finestra della console client. Si noti che una grandezza viene stampata per l'addizione e la sottrazione, ma non per la moltiplicazione e la divisione a causa della modalità di implementazione del servizio. Premere INVIO nella finestra del client per chiudere il 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.

Per configurare, compilare ed eseguire l'esempio

  1. Assicurati di aver eseguito la procedura di installazione di One-Time per gli esempi di Windows Communication Foundation.

  2. Per compilare l'edizione C# o Visual Basic .NET della soluzione, seguire le istruzioni in Compilazione degli esempi di Windows Communication Foundation.

  3. Per eseguire l'esempio in una configurazione con computer singolo o incrociato, seguire le istruzioni riportate in Esecuzione degli esempi di Windows Communication Foundation.