2010-09-24 12 views
12

Uso un set di servizi Web di una terza parte e ho riscontrato un piccolo inconveniente. Prima di eseguire manualmente un metodo per copiare ciascuna proprietà dall'origine alla destinazione, ho pensato di chiedere una soluzione migliore.2 oggetti, esattamente uguali (eccetto spazio dei nomi) C#

Ho 2 oggetti, uno di tipo Customer.CustomerParty e uno di tipo Appointment.CustomerParty. Gli oggetti CustomerParty sono in realtà proprietà e sotto-oggetto esattamente uguali. Ma non posso lanciare dall'uno all'altro.

Quindi, ho bisogno di trovare una certa persona dal webservice. Posso farlo chiamando Customer.FindCustomer (customerID) e restituisce un oggetto Customer.CustomerParty.

Ho bisogno di prendere quella persona che ho trovato e quindi usarli poche righe in basso in una richiesta "CreateAppointment". Appointment.CreateAppointment accetta un oggetto appuntamento e l'oggetto appuntamento contiene un oggetto CustomerParty.

Tuttavia, l'oggetto CustomerParty desiderato è Appointment.CustomerParty. Ho un cliente. ClienteParty.

Vedi cosa intendo? Eventuali suggerimenti?

+3

Poiché le classi sono da diversi spazi dei nomi significa che sono completamente diversi da CLR punto di vista. Ecco perché non puoi lanciarne uno da un altro. – uthark

risposta

7

Questo scenario è comune quando si scrivono modelli di dominio. Devi essenzialmente scrivere un traduttore di dominio tra i due oggetti. Puoi farlo in diversi modi, ma ti consiglio di avere un costruttore sottoposto a override (o un metodo statico) nel tipo di destinazione che accetta il tipo di servizio ed esegue il mapping. Poiché sono due tipi CLR, non è possibile eseguire il cast direttamente da uno all'altro. Devi copiare membro per membro.

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

Penso che dovrò seguire questa strada. :(Grazie per la risposta.Sfortunatamente StackOverflow non mi lascerà invogliare i tuoi post. OpenID non funziona su StackOverflow dal mio computer di lavoro - altri openid fanno, solo non StackOverlow. – Matt

+0

@Matt: Dovresti essere consapevole che sono metodi semplici come i metodi dinamici che non richiedono di scrivere da soli il codice di mappatura –

+0

Puoi anche ignorare il cast esplicito – Aren

1

sto usando set di un terzo partito di webservices ...

Supponendo che non è possibile modificare le classi, non sono consapevole di ogni modo in cui puoi cambiare il comportamento del cast. Almeno, non è molto più semplice della semplice scrittura di una funzione di mappatura CustomerToAppointmentPartyTranslator() ... :)

Supponendo che tu sia in una versione recente di C# (3.5, credo?), questo potrebbe essere un buon candidato per uno extension method.

12

Perché non usi AutoMapper? Poi si può fare:

TheirCustomerPartyClass source = WebService.ItsPartyTime(); 

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

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

Finché le proprietà sono identiche, è possibile creare una mappa molto semplice come questo:

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

Vedrò se possiamo aggiungere questo nel nostro progetto. Non sono sicuro se valga la pena, a questo punto, ma grazie per il suggerimento. Sono sicuro che risolverebbe il mio problema. Purtroppo StackOverflow non mi permetterà di svalutare i tuoi post. OpenID non funziona su StackOverflow dal mio computer di lavoro - altri siti openid funzionano, solo non StackOverlow. – Matt

+0

@Matt - Non c'è quasi nessun sovraccarico. AutoMapper è piuttosto leggero. Sicuramente vale la pena andare. – GenericTypeTea

+0

ha funzionato benissimo per me. Mapper.CreateMap (); Entities.CorporateDelayTracking.Delay convertedDelay = Mapper.Map (ritardo); – ScottLenart

0

Due classi con esattamente la stessa firma, in due spazi dei nomi diversi, sono due classi diverse. Non sarai in grado di convertire implicitamente tra di loro se non dichiarano esplicitamente come possono essere convertiti da uno all'altro utilizzando operatori impliciti o espliciti.

Ci sono alcune cose che potresti essere in grado di fare con la serializzazione. Le classi WCF DataContract su un lato non devono essere esattamente dello stesso tipo di DataContract sull'altro lato; devono solo avere la stessa firma e essere decorati in modo identico. Se questo è vero per i tuoi due oggetti, puoi usare DataContractSerializer per "convertire" i tipi attraverso la loro decorazione DataContract.

Se hai il controllo sull'implementazione di una classe o l'altra, puoi anche definire un operatore implicito o esplicito che definirà come l'altra classe può essere convertita alla tua. Questo probabilmente restituirà semplicemente un nuovo riferimento di una copia profonda dell'altro oggetto nel tuo tipo. Perché questo è il caso, lo definirei esplicito, per assicurarmi che la conversione venga eseguita solo quando è NECESSARIO (verrà utilizzata nei casi in cui si esegue il cast esplicito, ad esempio myAppCustomer = (Appointment.CustomerParty)myCustCustomer;).

Anche se non si controlla alcuna classe, è possibile scrivere un metodo di estensione o una terza classe che eseguirà questa conversione.

1

Un modo semplice e molto veloce di mappatura dei tipi sta usando il metodo PropertyCopy<TTarget>.CopyFrom<TSource>(TSource source) dalla libreria MiscUtil come descritto 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; 
    } 
} 
Problemi correlati