Domanda

Supponiamo che io abbia 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 SomeClass. C'è un modo semplice per copiarlo in una nuova istanza di SomeOtherClass senza copiare manualmente ogni membro?

AGGIORNAMENTO: Per la cronaca, sto non cercando di trasmettere l'istanza di SomeClass nell'istanza di SomeOtherClass. Quello che mi piacerebbe fare è qualcosa del genere:

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

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

Non voglio semplicemente farlo per ognuno a mano poiché questi oggetti hanno molte proprietà.

È stato utile?

Soluzione

" Saresti in grado di darmi un esempio di come posso farlo (o almeno indicarmi i metodi giusti da utilizzare)? Non riesco a trovarli su MSDN " & # 8211; Jason Baker

Jason, qualcosa del genere:

var props = typeof(Foo)
            .GetProperties(BindingFlags.Public | BindingFlags.Instance);

foreach (PropertyInfo p in props)
{
     // p.Name gives name of property
}

Suggerirei di scrivere uno strumento per sputare il codice necessario per un costruttore di copie, invece di farlo in modo riflessivo in fase di esecuzione - il che sarebbe meno performante.

Altri suggerimenti

Puoi creare operatori impliciti in ogni classe per fare la conversione per te:

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 funzionerebbero.

Il punto di un'interfaccia non è quello di non doverlo fare? Stai facendo qualcosa con l'implementazione concreta di SomeOtherClass? Invece di usare l'implementazione concreta, usa l'interfaccia e non dovrebbe importare se usi la classe SomeClass o SomeOther.

A parte questo, il meglio che potresti fare è scrivere una sorta di funzione di supporto (dovresti comunque farlo manualmente o esaminare la riflessione) che copia 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 dall'implementazione e di concentrarmi invece usando la tua interfaccia, quindi non importa cosa c'è sotto.

Reflection ... scorre attraverso ogni proprietà e impostala sulla proprietà corrispondente sull'altro oggetto.

Scopri la risposta di Joe per la soluzione Reflection.

Presumo che tu stia usando Visual Studio.

Hai familiarità con le scorciatoie ctrl + shift + r e ctrl + shift + p? In caso contrario, ctrl + maiusc + r inizia / termina la registrazione di una macro di battitura. ctrl + shift + p riproduce la macro registrata.

Quello che ho fatto quando ho impostato molte proprietà è copiare le dichiarazioni delle proprietà dove voglio che siano impostate e registrare una macro per mutare la dichiarazione in un'istruzione set e spostare il cursore sulla riga successiva , poi lo suono solo fino a quando non ho fatto tutte le istruzioni impostate.

No, per convertire in modo trasparente (cast) un oggetto da un tipo a un altro, la classe concreta sottostante dell'oggetto che hai, deve ereditare dalla classe in cui stai provando a lanciarlo, anche se entrambi implementano lo stesso interfaccia.

Pensaci, tutti e due gli oggetti devono avere in comune per implementare la stessa interfaccia è lo stesso sottoinsieme di firme dei metodi. Potrebbero non (probabilmente non avere) nemmeno le stesse proprietà o campi dati.

non funzionerebbe?

class MyClass : ICloneable
{
public MyClass()
{

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

return mc;
}

Devi solo chiamare: MyClass.Clone ().

   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);
   }

Mi è piaciuto quanto segue e funziona molto bene per convertire da un oggetto a un altro usando un operatore implicito:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("hello");
            ExecutionReport er = new ExecutionReport("ORDID1234",3000.43,DateTime.UtcNow);
            Order ord = new Order();
            ord = er;
            Console.WriteLine("Transferred values are : " + er.OrderId + "\t" + ord.Amount.ToString() + "\t" + ord.TimeStamp.ToString() + "\t");
            Console.ReadLine();
        }
    }


    public  class Order
    {
        public string OrderId { get; set; }
        public double Amount { get; set; }
        public DateTime TimeStamp { get; set; }
        public static implicit operator ExecutionReport(Order ord)
        {
            return new ExecutionReport()
            {
                OrderId = ord.OrderId,
                Amount = ord.Amount,
                TimeStamp = ord.TimeStamp
            };
        }
        public static implicit operator Order(ExecutionReport er)
        {
            return new Order()
            {
                OrderId = er.OrderId,
                Amount = er.Amount,
                TimeStamp = er.TimeStamp
            };
        }

        public Order()
        { }
    }

    public  class ExecutionReport
    {
        public string OrderId { get; set; }
        public double Amount { get; set; }
        public DateTime TimeStamp { get; set; }
        public ExecutionReport() { }
        public ExecutionReport(string orderId,double amount, DateTime ts)
        {
            OrderId = orderId; Amount = amount; TimeStamp = ts;
        }
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top