Nombres de contratos de datos
A veces un cliente y un servicio no comparten los mismos tipos. Todavía pueden pasar datos entre sí porque los contratos de datos son equivalentes en ambos lados. Equivalencia del contrato de datos se basa en nombres de contrato de datos y de miembro de datos y, por consiguiente, se proporciona un mecanismo para asignar tipos y miembros a esos nombres. En este tema se explican las reglas para nombrar contratos de datos, así como el comportamiento predeterminado de la infraestructura de Windows Communication Foundation (WCF) al crear los nombres.
Reglas básicas
Entre las reglas básicas con respecto a los nombres de los contratos de datos se incluyen:
Un nombre de contrato de datos completo se compone de un espacio de nombres y de un nombre.
Los miembros de datos solo tienen nombres, pero no espacios de nombres.
Al procesar los contratos de datos, la infraestructura de WCF distingue entre mayúsculas y minúsculas tanto en los espacios de nombres como en los nombres de contratos de datos y miembros de datos.
Espacios de nombres de contratos de datos
Un espacio de nombres de contrato de datos toma la forma de un Identificador uniforme de recursos (URI). El URI puede ser absoluto o relativo. De forma predeterminada, se asigna un espacio de nombres que procede del espacio de nombres de Common Language Runtime (CLR) de ese tipo a los contratos de datos de un tipo determinado.
De forma predeterminada, cualquier espacio de nombres CLR (con el formato Clr.Namespace) se asigna al espacio de nombres http://schemas.datacontract.org/2004/07/Clr.Namespace
. Para invalidar este valor predeterminado, aplique el atributo ContractNamespaceAttribute al ensamblado o módulo completo. De manera alternativa, para controlar el espacio de nombres del contrato de datos de cada tipo, establezca la propiedad Namespace del DataContractAttribute.
Nota
El espacio de nombres http://schemas.microsoft.com/2003/10/Serialization
se reserva y no se puede usar como un espacio de nombres del contrato de datos.
Nota
No puede invalidar el espacio de nombres predeterminado en tipos de contratos de datos que contengan declaraciones delegate
.
Nombres de contratos de datos
El nombre predeterminado de un contrato de datos de un tipo determinado es el nombre de ese tipo. Para invalidar el valor predeterminado, establezca la propiedad Name del DataContractAttribute en un nombre alternativo. Más adelante, en este tema, se describen las reglas especiales de los tipos genéricos, en la sección "Nombres de contratos de datos para tipos genéricos".
Nombres de miembros de datos
El nombre predeterminado de un miembro de datos de un campo o propiedad determinado es el nombre de ese campo o propiedad. Para invalidar el valor predeterminado, establezca la propiedad Name del DataMemberAttribute en un valor alternativo.
Ejemplos
El siguiente ejemplo muestra cómo puede invalidar el comportamiento de denominación predeterminado de contratos de datos y miembros de datos.
// 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
Nombres de contratos de datos para tipos genéricos
Existen reglas especiales para determinar los nombres de contratos de datos para tipos genéricos. Estas reglas ayudan a evitar las coincidencias de nombres de contratos de datos entre dos genéricos cerrados del mismo tipo genérico.
De forma predeterminada, el nombre del contrato de datos de un tipo genérico es el nombre del tipo, seguido por la cadena "Of", seguido por los nombres de contratos de datos de los parámetros genéricos, seguido por un hash calculado mediante los espacios de nombres de contrato de datos de los parámetros genéricos. Un hash es el resultado de una función matemática que actúa como una "huella" que identifica identifica de manera única una parte de datos. Cuando todos los parámetros genéricos son de tipo primitivo, se omite el hash.
Por ejemplo, vea los tipos del ejemplo siguiente.
[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
En este ejemplo, el tipo Drawing<Square,RegularRedBrush>
tiene el nombre de contrato de datos "DrawingOfSquareRedBrush5HWGAU6h", donde "5HWGAU6h" es un hash de los espacios de nombres "urn:default" y "urn:shapes". El tipo Drawing<Square,SpecialRedBrush>
tiene el nombre de contrato de datos "DrawingOfSquareRedBrushjpB5LgQ_S", donde "jpB5LgQ_S" es un hash de los espacios de nombres "urn:shapes" y "urn:special". Tenga en cuenta que, si no se utiliza el hash, los dos nombres son idénticos y se produce un conflicto de nombres.
Personalización de los nombres de contratos de datos para tipos genéricos
A veces, los nombres de contrato de datos generados para tipos genéricos, como se describió previamente, son inaceptables. Por ejemplo, puede conocer de antemano que no se encontrará con nombres coincidentes y puede que desee eliminar el hash. En este caso, puede utilizar la propiedad DataContractAttribute.Name para especificar una manera diferente de generar los nombres. Puede utilizar números dentro de llaves dentro de la propiedad Name
para hacer referencia a los nombres de contratos de datos de los parámetros genéricos. (0 hace referencia al primer parámetro, 1 hace referencia al segundo, etc.) Puede usar un signo de número (#) entre llaves para hacer referencia al hash. Puede utilizar cada una de estas referencias varias veces o ninguna.
Por ejemplo, el tipo genérico Drawing
anterior podría haberse declarado como se muestra en el ejemplo siguiente.
[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
En este caso, el tipo Drawing<Square,RegularRedBrush>
tiene del el nombre de contrato de datos "Drawing_using_RedBrush_brush_and_Square_shape". Tenga en cuenta que porque hay un "{#}" en la propiedad Name, el hash no forma parte del nombre y por esto el tipo es susceptible a las coincidencias de nombres; por ejemplo, el tipo Drawing<Square,SpecialRedBrush>
tendría exactamente el mismo nombre de contrato de datos.