Compartir a través de


Tipos conocidos

El ejemplo "KnownTypes" demuestra cómo especificar información sobre los tipos derivados en un contrato de datos. Los contratos de datos permiten pasar datos estructurados hacia y desde servicios. En la programación orientada a objetos, se puede usar un tipo que herede de otro tipo en lugar del tipo original. En la programación orientada a servicios, los esquemas en lugar de los tipos se comunican y, por tanto, no se conserva la relación entre tipos. El KnownTypeAttribute atributo permite incluir información sobre los tipos derivados en el contrato de datos. Si no se usa este mecanismo, no se puede enviar ni recibir un tipo derivado cuando se espera un tipo base.

Nota:

El procedimiento de instalación y las instrucciones de compilación de este ejemplo se encuentran al final de este tema.

El contrato de servicio del servicio usa números complejos, como se muestra en el código de ejemplo siguiente.

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

El DataContractAttribute y DataMemberAttribute se aplican a la clase ComplexNumber para indicar qué campos de la clase se pueden pasar entre el cliente y el servicio. La clase derivada ComplexNumberWithMagnitude se puede usar en lugar de ComplexNumber. El KnownTypeAttribute atributo del ComplexNumber tipo indica esto.

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

El ComplexNumberWithMagnitude tipo deriva de ComplexNumber pero agrega un miembro de datos adicional, 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(); }
    }
}

Para demostrar la característica de tipos conocidos, el servicio se implementa de tal manera que devuelve un ComplexNumberWithMagnitude solo para suma y resta. (Aunque el contrato especifica ComplexNumber, esto se permite debido al KnownTypeAttribute atributo ). La multiplicación y la división siguen devolviendo el tipo 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);
    }
}

En el cliente, tanto el contrato de servicio como el contrato de datos se definen en el archivo de origen generatedClient.cs, que genera la Herramienta de utilidad de metadatos de ServiceModel (Svcutil.exe) a partir de los metadatos del servicio. Dado que el KnownTypeAttribute atributo se especifica en el contrato de datos del servicio, el cliente puede recibir las ComplexNumber clases y ComplexNumberWithMagnitude al usar el servicio. El cliente detecta si ha recibido un ComplexNumberWithMagnitude y genera la salida adecuada.

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

Al ejecutar el ejemplo, las solicitudes y respuestas de la operación se muestran en la ventana de la consola del cliente. Tenga en cuenta que se imprime una magnitud para la suma y resta, pero no para la multiplicación y división debido a la forma en que se implementó el servicio. Presione ENTRAR en la ventana del cliente para apagar el cliente.

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.

Para configurar, compilar y ejecutar el ejemplo

  1. Asegúrese de que ha realizado el procedimiento de instalación única para los ejemplos de Windows Communication Foundation.

  2. Para compilar el código C# o Visual Basic .NET Edition de la solución, siga las instrucciones de Building the Windows Communication Foundation Samples.

  3. Para ejecutar el ejemplo en una configuración de una máquina única o entre máquinas, siga las instrucciones de Ejecución de los ejemplos de Windows Communication Foundation.