已知型別
KnownTypes 範例會示範如何在資料合約中指定有關衍生型別的資訊。 資料合約可以讓您在服務間來回傳遞結構化資料。 在物件導向程式設計中,繼承自另一個型別的型別可以用來取代原始型別。 在服務導向程式設計中,會使用結構描述而不是型別進行通訊,因此不會保留型別之間的關係。 KnownTypeAttribute 屬性可以讓關於衍生型別的資訊包含到資料合約中。 如果不使用這個機制,這時將無法傳送或接收衍生型別,因為預期是使用基底型別 (Base Type)。
注意
此範例的安裝程序與建置指示位於本主題的結尾。
此服務的服務合約會使用複數,如下列範例程式碼所示。
// 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 和 DataMemberAttribute 會套用至 ComplexNumber
類別,以便指示可在用戶端與服務之間傳遞的類別欄位。 衍生的 ComplexNumberWithMagnitude
類別可以用來取代 ComplexNumber
。 KnownTypeAttribute 型別的 ComplexNumber
屬性會指示這項資訊。
[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;
}
}
ComplexNumberWithMagnitude
型別衍生自 ComplexNumber
,但是其新增額外的資料成員,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(); }
}
}
為了示範已知型別功能,此服務會實作成只傳回加法與減法的 ComplexNumberWithMagnitude
。 (雖然合約會指定 ComplexNumber
,但是因為 KnownTypeAttribute
屬性的關係,所以仍會允許這項行為)。 乘法與除法仍然會傳回基底 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);
}
}
在用戶端上,服務合約與資料合約都會定義於 generatedClient.cs 原始程式檔中,而這個檔案是從服務中繼資料的 ServiceModel 中繼資料公用程式工具 (Svcutil.exe) 所產生的。 因為服務資料合約中是指定 KnownTypeAttribute 屬性,所以用戶端在使用服務時便能夠同時接收 ComplexNumber
和 ComplexNumberWithMagnitude
類別。 用戶端會偵測其是否收到 ComplexNumberWithMagnitude
,然後產生適當的輸出:
// 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");
}
當您執行範例時,作業的要求和回應會顯示在用戶端主控台視窗中。 請注意,此服務的實作方式會使得加法與減法列印值範圍,但是乘法與除法則不會列印。 在用戶端視窗中按下 ENTER 鍵,即可關閉用戶端。
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.
若要安裝、建置及執行範例
若要建置方案的 C# 或 Visual Basic .NET 版本,請遵循 Building the Windows Communication Foundation Samples中的指示。
若要在單一或多部電腦組態中執行此範例,請遵循執行 Windows Communication Foundation 範例中的指示進行。