2010-09-24 11 views
12

Estoy usando un conjunto de servicios web de un tercero, y me he topado con un pequeño inconveniente. Antes de hacer manualmente un método para copiar cada propiedad desde el origen hasta el destino, pensé que podría pedir aquí una mejor solución.2 objetos, exactamente iguales (excepto el espacio de nombres) C#

Tengo 2 objetos, uno de tipo Customer.CustomerParty y uno de tipo Appointment.CustomerParty. Los objetos CustomerParty son en realidad propiedad y sub-objeto exactamente iguales. Pero no puedo lanzar de 1 a la otra.

Por lo tanto, necesito encontrar una determinada persona del servicio web. Puedo hacerlo llamando a Customer.FindCustomer (customerID) y devuelve un objeto Customer.CustomerParty.

Necesito tomar a esa persona que encontré y luego usarlas unas pocas líneas abajo en una solicitud de "Crear una cita". Appointment.CreateAppointment toma un objeto de cita y el objeto de cita contiene un objeto CustomerParty.

Sin embargo, el objeto CustomerParty que desea es realmente Appointment.CustomerParty. Tengo una Customer.CustomerParty.

¿Ves lo que digo? ¿Alguna sugerencia?

+3

Dado que las clases son de diferentes espacios de nombres que significa que son completamente diferentes de CLR punto de vista. Es por eso que no puedes lanzar uno de otro. – uthark

Respuesta

7

Este escenario es común al escribir patrones de dominio. Básicamente, necesitas escribir un traductor de dominio entre los dos objetos. Puede hacerlo de varias formas, pero recomiendo tener un constructor anulado (o un método estático) en el tipo de destino que toma el tipo de servicio y realiza la asignación. Dado que son dos tipos de CLR, no se puede transmitir directamente de uno a otro. Debe copiar miembro por miembro.

public class ClientType 
{ 
    public string FieldOne { get; set; } 
    public string FieldTwo { get; set; } 

    public ClientType() 
    { 
    } 

    public ClientType(ServiceType serviceType) 
    { 
     this.FieldOne = serviceType.FieldOne; 
     this.FieldTwo = serviceType.FieldTwo; 
    } 
} 

O

public static class DomainTranslator 
{ 
    public static ServiceType Translate(ClientType type) 
    { 
     return new ServiceType { FieldOne = type.FieldOne, FieldTwo = type.FieldTwo }; 
    } 
} 
+0

Creo que voy a tener que seguir esta ruta. :(Gracias por la respuesta. Desafortunadamente, StackOverflow no me permite votar por sus publicaciones. OpenID no funciona en StackOverflow desde mi computadora de trabajo - otros sitios abiertos sí, simplemente no StackOverlow. – Matt

+0

@Matt: Debe tener en cuenta que hay son formas simples como métodos dinámicos que no requieren que usted escriba el código de mapeo usted mismo. –

+0

También puede anular el molde explícito – Aren

1

estoy usando conjunto de servicios web un tercio de fiesta ...

Suponiendo que no puede modificar las clases, no estoy consciente de cualquier forma en que pueda cambiar el comportamiento de lanzamiento. Al menos, de ninguna manera eso no es mucho, mucho más complicado que simplemente escribir una función de asignación CustomerToAppointmentPartyTranslator() ... :)

Suponiendo que está en una versión reciente de C# (3.5, ¿lo creo?), esto podría ser un buen candidato para un extension method.

12

¿Por qué no usa AutoMapper? A continuación, puede hacer:

TheirCustomerPartyClass source = WebService.ItsPartyTime(); 

YourCustomerPartyClass converted = 
    Mapper.Map<TheirCustomerPartyClass, YourCustomerPartyClass>(source); 

TheirCustomerPartyClass original = 
    Mapper.Map<YourCustomerPartyClass, TheirCustomerPartyClass>(converted); 

Como siempre que las propiedades son idénticos, puede crear un mapa muy simple como esto:

Mapper.CreateMap<TheirCustomerPartyClass, YourCustomerPartyClass>(); 
Mapper.CreateMap<YourCustomerPartyClass, TheirCustomerPartyClass>(); 
+0

Veré si podemos agregar esto a nuestro proyecto. No estoy seguro de si vale la pena la sobrecarga en este punto, pero gracias por la sugerencia. Estoy seguro de que resolvería mi problema. Lamentablemente, StackOverflow no me permitirá votar sus publicaciones. OpenID no funciona en StackOverflow desde mi computadora de trabajo; otros sitios abiertos lo hacen, simplemente no StackOverlow. – Matt

+0

@Matt: casi no hay gastos generales. AutoMapper es bastante ligero. Definitivamente vale la pena ir. – GenericTypeTea

+0

Funcionó muy bien para mí. Mapper.CreateMap (); Entities.CorporateDelayTracking.Delay convertedDelay = Mapper.Map (retraso); – ScottLenart

0

Dos clases con exactamente la misma firma, en dos espacios de nombres diferentes, son dos clases diferentes No podrá convertir implícitamente entre ellos si no establecen explícitamente cómo se pueden convertir de uno a otro mediante operadores implícitos o explícitos.

Hay algunas cosas que puede hacer con la serialización. Las clases WCF DataContract en un lado no tienen que ser exactamente del mismo tipo que DataContract en el otro lado; solo tienen que tener la misma firma y estar decorados de forma idéntica. Si esto es cierto para sus dos objetos, puede usar un DataContractSerializer para "convertir" los tipos a través de su decoración de DataContract.

Si tiene control sobre la implementación de una clase u otra, también puede definir un operador implícito o explícito que definirá cómo la otra clase se puede convertir a la suya. Esto probablemente simplemente devuelva una nueva referencia de una copia profunda del otro objeto en su tipo. Debido a que este es el caso, lo definiría como explícito, para asegurarme de que la conversión solo se realice cuando NECESITAS (se usará en casos en los que explícitamente se emita, como myAppCustomer = (Appointment.CustomerParty)myCustCustomer;).

Incluso si no controla ninguna clase, puede escribir un método de extensión, o una tercera clase, que realizará esta conversión.

1

Una manera simple y muy rápida de la cartografía de los tipos está utilizando el método PropertyCopy<TTarget>.CopyFrom<TSource>(TSource source) de la biblioteca MiscUtil como se describe here:

using MiscUtil.Reflection; 

class A 
{ 
    public int Foo { get; set; } 
} 

class B 
{ 
    public int Foo { get; set; } 
} 

class Program 
{ 
    static void Main() 
    { 
     A a = new A(); 
     a.Foo = 17; 
     B b = PropertyCopy<B>.CopyFrom(a); 

     bool success = b.Foo == 17; // success is true; 
    } 
} 
Cuestiones relacionadas