Namn på datakontrakt
Ibland delar inte en klient och en tjänst samma typer. De kan fortfarande skicka data till varandra så länge datakontrakten är likvärdiga på båda sidor. Data contract equivalence baseras på namn på datakontrakt och datamedlemmar, och därför tillhandahålls en mekanism för att mappa typer och medlemmar till dessa namn. Det här avsnittet beskriver reglerna för namngivning av datakontrakt samt standardbeteendet för WCF-infrastrukturen (Windows Communication Foundation) när du skapar namn.
Grundläggande regler
Grundläggande regler för namngivning av datakontrakt är:
Ett fullständigt kvalificerat datakontraktsnamn består av ett namnområde och ett namn.
Datamedlemmar har bara namn, men inga namnområden.
Vid bearbetning av datakontrakt är WCF-infrastrukturen skiftlägeskänslig för både namnrymderna och namnen på datakontrakt och datamedlemmar.
Namnområden för datakontrakt
Ett namnområde för datakontrakt har formen av en URI (Uniform Resource Identifier). URI:n kan vara antingen absolut eller relativ. Som standard tilldelas datakontrakt för en viss typ ett namnområde som kommer från CLR-namnområdet (Common Language Runtime) av den typen.
Som standard mappas alla givna CLR-namnområden (i formatet Clr.Namespace) till namnområdet http://schemas.datacontract.org/2004/07/Clr.Namespace
. Om du vill åsidosätta den här standardinställningen ContractNamespaceAttribute använder du attributet för hela modulen eller sammansättningen. Du kan också styra datakontraktets namnområde för varje typ genom att ange Namespace egenskapen för DataContractAttribute.
Kommentar
Namnområdet http://schemas.microsoft.com/2003/10/Serialization
är reserverat och kan inte användas som ett datakontraktsnamnområde.
Kommentar
Du kan inte åsidosätta standardnamnområdet i datakontraktstyper som innehåller delegate
deklarationer.
Namn på datakontrakt
Standardnamnet för ett datakontrakt för en viss typ är namnet på den typen. Om du vill åsidosätta standardinställningen Name anger du egenskapen DataContractAttribute för till ett alternativt namn. Särskilda regler för generiska typer beskrivs i "Namn på datakontrakt för generiska typer" senare i det här avsnittet.
Namn på datamedlem
Standardnamnet för en datamedlem för ett visst fält eller en viss egenskap är namnet på det fältet eller egenskapen. Om du vill åsidosätta standardvärdet anger du Name egenskapen DataMemberAttribute för till ett alternativt värde.
Exempel
I följande exempel visas hur du kan åsidosätta standardbeteendet för namngivning av datakontrakt och datamedlemmar.
// This overrides the standard namespace mapping for all contracts
// in Contoso.CRM.
[assembly: ContractNamespace("http://schemas.example.com/crm",
ClrNamespace = "Contoso.CRM")]
namespace Contoso.CRM
{
// The namespace is overridden to become:
// http://schemas.example.com/crm.
// But the name is the default "Customer".
[DataContract]
public class Customer
{
// Code not shown.
}
}
namespace Contoso.OrderProc
{
[DataContract]
public class PurchaseOrder
{
// This data member is named "Amount" by default.
[DataMember]
public double Amount;
// The default is overridden to become "Address".
[DataMember(Name = "Address")]
public string Ship_to;
}
// The namespace is the default value:
// http://schemas.datacontract.org/2004/07/Contoso.OrderProc
// The name is "PurchaseOrder" instead of "MyInvoice".
[DataContract(Name = "PurchaseOrder")]
public class MyInvoice
{
// Code not shown.
}
// The contract name is "Payment" instead of "MyPayment"
// and the Namespace is "http://schemas.example.com" instead
// of the default.
[DataContract(Name = "Payment",
Namespace = "http://schemas.example.com")]
public class MyPayment
{
// Code not shown.
}
}
' This overrides the standard namespace mapping for all contracts
' in Contoso.CRM.
<Assembly: ContractNamespace("http://schemas.example.com/crm", _
ClrNamespace:="Contoso.CRM")>
Namespace Contoso.CRM
' The namespace is overridden to become:
' http://schemas.example.com/crm.
' But the name is the default "Customer".
<DataContract()> _
Public Class Customer
' Code not shown.
End Class
End Namespace
Namespace Contoso.OrderProc
<DataContract()> _
Public Class PurchaseOrder
' This data member is named "Amount" by default.
<DataMember()> _
Public Amount As Double
' The default is overridden to become "Address".
<DataMember(Name:="Address")> _
Public Ship_to As String
End Class
' The namespace is the default value:
' http://schemas.datacontract.org/2004/07/Contoso.OrderProc
' The name is "PurchaseOrder" instead of "MyInvoice".
<DataContract(Name:="PurchaseOrder")> _
Public Class MyInvoice
' Code not shown.
End Class
' The contract name is "Payment" instead of "MyPayment"
' and the Namespace is "http://schemas.example.com" instead
' of the default.
<DataContract(Name:="Payment", [Namespace]:="http://schemas.example.com")> _
Public Class MyPayment
' Code not shown.
End Class
End Namespace
Namn på datakontrakt för generiska typer
Det finns särskilda regler för att fastställa namn på datakontrakt för generiska typer. Dessa regler hjälper till att undvika kollisioner mellan datakontraktets namn mellan två slutna generiska objekt av samma generiska typ.
Som standard är namnet på datakontraktet för en allmän typ namnet på typen, följt av strängen "Av", följt av datakontraktsnamnen för de generiska parametrarna, följt av en hash som beräknas med hjälp av datakontraktets namnområden för de generiska parametrarna. En hash är resultatet av en matematisk funktion som fungerar som ett "fingeravtryck" som unikt identifierar en databit. När alla generiska parametrar är primitiva typer utelämnas hashen.
Se till exempel typerna i följande exempel.
[DataContract]
public class Drawing<Shape, Brush>
{
// Code not shown.
}
[DataContract(Namespace = "urn:shapes")]
public class Square
{
// Code not shown.
}
[DataContract(Name = "RedBrush", Namespace = "urn:default")]
public class RegularRedBrush
{
// Code not shown.
}
[DataContract(Name = "RedBrush", Namespace = "urn:special")]
public class SpecialRedBrush
{
// Code not shown.
}
<DataContract()> _
Public Class Drawing(Of Shape, Brush)
<DataContract([Namespace]:="urn:shapes")> _
Public Class Square
' Code not shown.
End Class
<DataContract(Name:="RedBrush", [Namespace]:="urn:default")> _
Public Class RegularRedBrush
' Code not shown.
End Class
<DataContract(Name:="RedBrush", [Namespace]:="urn:special")> _
Public Class SpecialRedBrush
' Code not shown.
End Class
End Class
I det här exemplet har typen Drawing<Square,RegularRedBrush>
datakontraktnamnet "DrawingOfSquareRedBrush5HWGAU6h", där "5HWGAU6h" är en hash för namnrymderna "urn:shapes" och "urn:default". Typen Drawing<Square,SpecialRedBrush>
har datakontraktsnamnet "DrawingOfSquareRedBrushjpB5LgQ_S", där "jpB5LgQ_S" är en hash för namnrymderna "urn:shapes" och "urn:special". Observera att om hashen inte används är de två namnen identiska och därför uppstår en namnkollision.
Anpassa namn på datakontrakt för generiska typer
Ibland är de datakontraktsnamn som genereras för generiska typer, enligt beskrivningen tidigare, oacceptabla. Du kanske till exempel vet i förväg att du inte kommer att stöta på namnkollisioner och kanske vill ta bort hashen. I det här fallet kan du använda egenskapen DataContractAttribute.Name för att ange ett annat sätt att generera namn. Du kan använda tal i klammerparenteser i Name
egenskapen för att referera till namn på datakontrakt för de allmänna parametrarna. (0 refererar till den första parametern, 1 refererar till den andra och så vidare.) Du kan använda ett taltecken (#) inuti klammerparenteser för att referera till hashen. Du kan använda var och en av dessa referenser flera gånger eller inte alls.
Till exempel kan den föregående generiska Drawing
typen ha deklarerats enligt följande exempel.
[DataContract(Name = "Drawing_using_{1}_brush_and_{0}_shape")]
public class Drawing<Shape, Brush>
{
// Code not shown.
}
<DataContract(Name:="Drawing_using_{1}_brush_and_{0}_shape")> _
Public Class Drawing(Of Shape, Brush)
' Code not shown.
End Class
I det här fallet har typen Drawing<Square,RegularRedBrush>
namnet på datakontraktet "Drawing_using_RedBrush_brush_and_Square_shape". Observera att eftersom det finns en "{#}" i Name egenskapen är hashen inte en del av namnet, och därför är typen mottaglig för namngivningskollisioner. Till exempel skulle typen Drawing<Square,SpecialRedBrush>
ha exakt samma datakontraktsnamn.