Utilizzando un’interfaccia per la conversione di un oggetto da un tipo a un altro?

Supponiamo di avere due classi con la stessa interfaccia:

interface ISomeInterface 
{
    int foo{get; set;}
    int bar{get; set;}
}

class SomeClass : ISomeInterface {}

class SomeOtherClass : ISomeInterface {}

Supponiamo di avere un’istanza di ISomeInterface che rappresenta un SomeClass. C’è un modo semplice per copiare in una nuova istanza di SomeOtherClass senza copiare ogni membro a mano?

AGGIORNAMENTO: Per la cronaca, sto non cercando di gettare l’istanza di SomeClass nell’istanza di SomeOtherClass. Quello che mi piacerebbe fare è qualcosa di simile a questo:

ISomeInterface sc = new SomeClass() as ISomeInterface;
SomeOtherClass soc = new SomeOtherClass();

soc.foo = sc.foo;
soc.bar = soc.bar;

Non voglio più avere a che fare che per ogni mano, in quanto tali oggetti hanno un sacco di proprietà.

InformationsquelleAutor Jason Baker | 2008-11-19



9 Replies
  1. 3

    “Saresti in grado di farmi un esempio di come posso fare (o almeno mi punto verso destra, metodi di utilizzo)? Non mi sembra di essere in grado di trovarli su MSDN” – Jason Baker

    Jason, qualcosa di simile al seguente:

    var props = typeof(Foo)
                .GetProperties(BindingFlags.Public | BindingFlags.Instance);
    
    foreach (PropertyInfo p in props)
    {
         //p.Name gives name of property
    }

    Io suggerirei di scrivere un tool per sputare fuori il codice che ti serve per un costruttore di copia, anziché farlo aggiornati in fase di runtime, che avrebbe dovuto essere meno performante.

    • Ma prima di pre-ottimizzare, provare con l’utilizzo on-the-fly di riflessione. Se stai facendo qualcosa di simile a un standard line-of-business app, un po ‘ di riflessione su proprietà probabilmente non è un grosso problema, e la flessibilità di avere self-correcting code quando gli oggetti sono aggiunti o nomi cambiato è bello.
    • sì, ottimo punto di Chris. Io secondo che
  2. 9

    È possibile creare implicita operatori in ogni classe per fare la conversione per voi:

    public class SomeClass
    {
        public static implicit operator SomeOtherClass(SomeClass sc)
        {
            //replace with whatever conversion logic is necessary
            return new SomeOtherClass()
            {
                foo = sc.foo,
                bar = sc.bar
            }
        }
    
        public static implicit operator SomeClass(SomeOtherClass soc)
        {
            return new SomeClass()
            {
                foo = soc.foo,
                bar = soc.bar
            }
        }
        //rest of class here
    }

    e poi SomeOtherClass soc = sc; e viceversa, lavoro.

  3. 6

    Non è il punto di un’interfaccia di non avere a che fare? Stai facendo qualcosa con l’attuazione concreta di SomeOtherClass? Invece di utilizzare l’attuazione concreta, utilizzare l’interfaccia e non importa se si utilizza SomeClass o SomeOther classe.

    Oltre a questo, il meglio che si possa fare è quello di scrivere una sorta di funzione di supporto (che ci devono ancora farlo manualmente, o guardare in riflessione) che le copie di ogni Proprietà sull’Interfaccia che sarebbe simile a questa:

       public ISomeInterface CopyValues(ISomeInterface fromSomeClass, ISomeInterface toSomeOtherClass)
       {
        //copy properties here
        return toSomeOtherClass;
        }

    Tuttavia, il mio primo istinto sarebbe quello di dire di stare lontano da l’implementazione e concentrarsi utilizzando l’interfaccia, invece, allora non importa ciò che giace al di sotto.

  4. 4

    Riflessione … loop attraverso ogni proprietà, e la corrispondente proprietà su di un altro oggetto.

    • Sareste in grado di darmi un esempio di come posso fare (o almeno mi punto verso destra, metodi di utilizzo)? Non mi sembra di essere in grado di trovarli su MSDN. :-/
    • Questo non funziona se il propertys sono di diversi tipi… Tuo codice per confrontare i tipi di proprietà così come i loro nomi… E poi hai anche il problema di trattare con il tipo di riferimento proprtys – (copia Profonda o superficiale copia)?
  5. 4

    Check out Joe risposta per la Riflessione soluzione.

    Presumo si utilizza Visual Studio.

    Hai familiarità con la combinazione di tasti ctrl+shift+r ctrl+maiusc+p scorciatoie?
    Se non, ctrl+maiusc+r inizia/termina la registrazione di una sequenza di tasti macro.
    ctrl+maiusc+p svolge la macro registrata.

    Quello che ho fatto quando ho messo un sacco di proprietà è quello di copiare le dichiarazioni di proprietà dove voglio essere e di registrare una macro per mutando la dichiarazione di un set di istruzione e di spostare il cursore alla riga successiva, quindi mi basta giocare fino a quando ho tutto il set di istruzioni di fatto.

    • Grande punta sulla macro! Non era a conoscenza prima di loro, e hanno trovato un uso per esso già. Grazie.
    • Delphi ha avuto questa caratteristica per un lungo periodo di tempo. Ero così felice quando ho imparato su di esso. Ho incontrato altri editori che questa funzione.
    • Inoltre, verificare che cosa succede se si digita “se”, quindi premere il tasto tab in VS.
    • Tipo di prop quindi premere tab
  6. 3

    No, in modo trasparente la conversione (cast) di un oggetto da un tipo ad un altro, il sottostante calcestruzzo classe di oggetto, deve ereditare dalla classe che si sta tentando di eseguire il cast, anche se entrambi hanno inplement la stessa interfaccia.

    Pensate, per tutti i due oggetti hanno in comune per implementare la stessa interfaccia è la stessa sottoinsieme di firme di metodo. Non potrebbe (probabilmente non) hanno anche la stessa proprietà o campi di dati.

    • Forse ho misworded me. Io preferirei non per il cast. Sarebbe un bene per me per copiare i valori da un’istanza all’altra. Non voglio scrivere quelle a mano (gli oggetti hanno un sacco di proprietà).
    • Cosa intendi con “non voglio più scrivere quelle a mano”? Si potrebbe scrivere un strumento di riflessione, che prende in esame tutti i campi, in una classe e guarda 4 gonzi in un altro, e poi dove c’è una partita, copiare il valore… Ma sarebbe necessario confrontare tipi di dati e di nomi di campo…. disordinato!
    • Altrimenti, il codice a mano, campo per campo, o proprietà per proprietà…
    • Hmmm…. Prendo questo a significare “non vi è alcun modo semplice per fare questo.” :-/
    • Se ci sono davvero un sacco di proprietà e poi scrivere un programma che prende in esame l’oggetto di riflessione e sputa fuori il codice che ti serve per un costruttore di copia.
  7. 3

    non sarebbe questo lavoro?

    class MyClass : ICloneable
    {
    public MyClass()
    {
    
    }
    public object Clone() //ICloneable implementation
    {
    MyClass mc = this.MemberwiseClone() as MyClass;
    
    return mc;
    }

    Devi solo chiamare: MyClass.Clone().

    • Ho pensato anch’io, ma l’unico problema è che la base di classe che eredita da ha una propria implementazione del Clone che restituisce un oggetto dello stesso tipo. :-/
  8. 3
       ISomeInterface sc = new SomeClass() as ISomeInterface;
       SomeOtherClass soc = new SomeOtherClass();
       foreach (PropertyInfo info in typeof(ISomeInterface)
                                         .GetProperties(BindingFlags.Instance
                                                         |BindingFlags.Public))
       {
           info.SetValue(soc,info.GetValue(sc,null),null);
       }
  9. 2

    Ho fatto come il seguente e funziona molto bene per convertire un oggetto in un altro tramite operatore implicito:

    Programma di classe 
    { 
    static void Main(string[] args) 
    { 
    Console.WriteLine("ciao"); 
    ExecutionReport er = new ExecutionReport("ORDID1234",3000.43,DateTime.UtcNow); 
    Ordine ord = new Order(); 
    ord = er; 
    Console.WriteLine("Trasferito valori sono :" + er.Idordine + "\t" + ord.Importo.ToString() + "\t" + ord.TimeStamp.ToString() + "\t"); 
    Console.ReadLine(); 
    } 
    } 
    
    
    public class Ordine 
    { 
    public string Idordine { get; set; } 
    pubblica a doppia Somma, { get; set; } 
    pubblico DateTime TimeStamp { get; set; } 
    public static operatore implicito ExecutionReport(Ordine ord) 
    { 
    return new ExecutionReport() 
    { 
    Idordine = ord.Idordine, 
    Importo = ord.Quantità, 
    TimeStamp = ord.TimeStamp 
    }; 
    } 
    public static operatore implicito Ordine(ExecutionReport er) 
    { 
    return new Order() 
    { 
    Idordine = er.Idordine, 
    Importo = er.Quantità, 
    TimeStamp = er.TimeStamp 
    }; 
    } 
    
    Ordine pubblico() 
    { } 
    } 
    
    public class ExecutionReport 
    { 
    public string Idordine { get; set; } 
    pubblica a doppia Somma, { get; set; } 
    pubblico DateTime TimeStamp { get; set; } 
    pubblico ExecutionReport() { } 
    pubblico ExecutionReport(string idordine,quantità doppia, DateTime ts) 
    { 
    Idordine = idordine; Importo = importo; il TimeStamp = ts; 
    } 
    } 
    
    • +1 – Ottimo commento di un modo per fare questo uso degli operatori. Penso che in questo caso è meglio di riflessione per fare la copia.

Lascia un commento