Usando uma interface para converter um objeto de um tipo para outro?
Pergunta
Suponha que eu tenho duas classes com a mesma interface:
interface ISomeInterface
{
int foo{get; set;}
int bar{get; set;}
}
class SomeClass : ISomeInterface {}
class SomeOtherClass : ISomeInterface {}
Suponha que eu tenho uma instância de ISomeInterface que representa uma SomeClass. Existe uma maneira fácil de copiar isso em uma nova instância do SomeOtherClass sem copiar cada membro com a mão?
UPDATE: Para o registro, eu sou não tentando lançar a instância do SomeClass na instância de SomeOtherClass. O que eu gostaria de fazer é algo como isto:
ISomeInterface sc = new SomeClass() as ISomeInterface;
SomeOtherClass soc = new SomeOtherClass();
soc.foo = sc.foo;
soc.bar = soc.bar;
Eu só não quero ter que fazer isso para cada à mão como esses objetos têm muitas propriedades.
Solução
"? Você seria capaz de me dar um exemplo de como eu posso fazer isso (ou pelo menos apontar-me no sentido dos métodos adequados para ser utilizando) Eu não parecem ser capazes de encontrá-los no MSDN" - Jason Baker
Jason, algo como o seguinte:
var props = typeof(Foo)
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in props)
{
// p.Name gives name of property
}
Eu sugiro escrever uma ferramenta para cuspir o código que você precisa para um construtor de cópia, em oposição a fazê-lo reflexivamente em tempo de execução -. O que seria menos eficaz
Outras dicas
Você pode criar operadores implícitos em cada classe para fazer a conversão para você:
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, em seguida, SomeOtherClass soc = sc;
e vice-versa iria funcionar.
Não é o ponto de uma interface para não ter de fazer isso? Você está fazendo algo com a implementação concreta de SomeOtherClass? Em vez de usar a implementação concreta, use a interface e não importa devem se você usar SomeClass ou someother classe.
Além disso, o melhor que você pode fazer é escrever uma espécie de função auxiliar (você ainda teria que fazê-lo manualmente, ou olhar para reflexão) que copia cada propriedade na interface que ficaria assim:
public ISomeInterface CopyValues(ISomeInterface fromSomeClass, ISomeInterface toSomeOtherClass)
{
//copy properties here
return toSomeOtherClass;
}
No entanto, meu primeiro instinto seria dizer ficar longe da implementação e concentrado usando sua interface em vez disso, então ele não vai importa o que está deitado por baixo.
Reflexão ... loop através de cada propriedade, e configurá-lo na propriedade correspondente no outro objeto.
Confira resposta de Joe para a solução Reflection.
Eu suponho que você estiver usando o Visual Studio.
Você está familiarizado com o CTRL + SHIFT + R e atalhos Ctrl + Shift + P? Se não, ctrl + shift + r começa / termina a gravação de uma macro keystroke. ctrl + shift + p desempenha a macro gravada.
O que eu fiz quando eu puser um monte de propriedades é copiar as declarações de propriedade para onde eu quero que eles sejam definir e gravar uma macro para mutando a declaração com um comunicado conjunto e movendo o cursor para a próxima linha , então eu apenas reproduzi-lo até que eu tenha todas as instruções do conjunto feito.
Não, para converter de forma transparente (cast) um objeto de um tipo para outro, a classe concreta subjacente do objeto que você tem, deve herdar a classe o que você está tentando lançá-lo, mesmo se ambos inplement o mesmo interface.
Pense nisso, todos os dois objetos têm que ter em comum para implementar a mesma interface é o mesmo subconjunto de assinaturas de método. Eles não poderia (provavelmente não) ainda têm as mesmas propriedades ou campos de dados.
não seria este trabalho?
class MyClass : ICloneable
{
public MyClass()
{
}
public object Clone() // ICloneable implementation
{
MyClass mc = this.MemberwiseClone() as MyClass;
return mc;
}
Você só tem que chamada: 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);
}
Eu fiz como o seguinte e ele funciona muito bem para converter de um objeto em outro operador implícito usando:
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; } }