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.

Foi útil?

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;
        }
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top