Usi un'interfaccia per convertire un oggetto da un tipo a un altro?
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à.
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; } }