Kända typer
Exemplet KnownTypes visar hur du anger information om härledda typer i ett datakontrakt. Med datakontrakt kan du skicka strukturerade data till och från tjänster. I objektorienterad programmering kan en typ som ärver från en annan typ användas i stället för den ursprungliga typen. I tjänstorienterad programmering kommuniceras scheman i stället för typer och därför bevaras inte relationen mellan typerna. Attributet KnownTypeAttribute tillåter att information om härledda typer inkluderas i datakontraktet. Om den här mekanismen inte används kan inte en härledd typ skickas eller tas emot där en bastyp förväntas.
Kommentar
Installationsproceduren och bygginstruktionerna för det här exemplet finns i slutet av det här avsnittet.
Tjänstkontraktet för tjänsten använder komplexa tal, enligt följande exempelkod.
// 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);
}
Och DataContractAttributeDataMemberAttribute tillämpas på ComplexNumber
klassen för att ange vilka fält i klassen som kan skickas mellan klienten och tjänsten. Den härledda ComplexNumberWithMagnitude
klassen kan användas i stället för ComplexNumber
. Attributet KnownTypeAttribute för typen ComplexNumber
anger detta.
[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;
}
}
Typen ComplexNumberWithMagnitude
härleds från ComplexNumber
men lägger till ytterligare en datamedlem, 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(); }
}
}
För att demonstrera funktionen för kända typer implementeras tjänsten på ett sådant sätt att den endast returnerar en ComplexNumberWithMagnitude
för addition och subtraktion. (Även om kontraktet anger tillåts ComplexNumber
detta på grund av attributet KnownTypeAttribute
). Multiplikation och division returnerar fortfarande bastypen 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);
}
}
På klienten definieras både tjänstkontraktet och datakontraktet i källfilen generatedClient.cs, som genereras av ServiceModel Metadata Utility Tool (Svcutil.exe) från tjänstmetadata. KnownTypeAttribute Eftersom attributet anges i tjänstens datakontrakt kan klienten ta emot både klasserna ComplexNumber
och ComplexNumberWithMagnitude
när tjänsten används. Klienten identifierar om den har en ComplexNumberWithMagnitude
och genererar lämpliga utdata:
// 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");
}
När du kör exemplet visas begäranden och svar för åtgärden i klientkonsolfönstret. Observera att en omfattning skrivs ut för addition och subtraktion men inte för multiplikation och division på grund av hur tjänsten implementerades. Tryck på RETUR i klientfönstret för att stänga av klienten.
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.
Så här konfigurerar du, skapar och kör exemplet
Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.
Om du vill skapa C# eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel.
Om du vill köra exemplet i en konfiguration med en eller flera datorer följer du anvisningarna i Köra Windows Communication Foundation-exempel.