Pregunta

Supongamos que tengo dos clases con la misma interfaz:

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

class SomeClass : ISomeInterface {}

class SomeOtherClass : ISomeInterface {}

Supongamos que tengo una instancia de ISomeInterface que representa un SomeClass. ¿Hay una manera fácil de copiar eso en una nueva instancia de SomeOtherClass sin copiar cada miembro a mano?

ACTUALIZACIÓN: Para el registro, no estoy tratando de convertir la instancia de SomeClass en la instancia de SomeOtherClass. Lo que me gustaría hacer es algo como esto:

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

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

Simplemente no quiero tener que hacer eso a mano ya que estos objetos tienen muchas propiedades.

¿Fue útil?

Solución

" ¿Podría darme un ejemplo de cómo puedo hacer eso (o al menos señalarme los métodos correctos para usar)? Parece que no puedo encontrarlos en MSDN " & # 8211; Jason Baker

Jason, algo así como lo siguiente:

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

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

Sugeriría escribir una herramienta para escupir el código que necesita para un constructor de copias, en lugar de hacerlo reflexivamente en tiempo de ejecución, lo que sería menos eficaz.

Otros consejos

Puede crear operadores implícitos en cada clase para hacer la conversión por usted:

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
}

y luego SomeOtherClass soc = sc; y viceversa funcionarían.

¿No es el objetivo de una interfaz no tener que hacer eso? ¿Estás haciendo algo con la implementación concreta de SomeOtherClass? En lugar de usar la implementación concreta, use la interfaz y no debería importar si usa la clase SomeClass o SomeOther.

Aparte de eso, lo mejor que podría hacer es escribir algún tipo de función auxiliar (aún tendría que hacerlo manualmente, o mirar en la reflexión) que copia cada propiedad en la interfaz que se vería así:

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

Sin embargo, mi primer instinto sería decir que se mantenga alejado de la implementación y se concentre usando su interfaz en su lugar, entonces no importará lo que hay debajo.

Reflexión ... recorra cada propiedad y configúrela en la propiedad correspondiente del otro objeto.

Vea la respuesta de Joe para la solución Reflection.

Supongo que está utilizando Visual Studio.

¿Está familiarizado con los atajos ctrl + shift + r y ctrl + shift + p? Si no, ctrl + shift + r comienza / finaliza la grabación de una macro de pulsación de tecla. ctrl + shift + p reproduce la macro grabada.

Lo que hice cuando configuré muchas propiedades es copiar las declaraciones de propiedades donde quiero que se configuren y grabar una macro para mutar la declaración a una instrucción establecida y mover el cursor a la siguiente línea , luego lo juego hasta que tenga todas las declaraciones establecidas.

No, para convertir (emitir) de forma transparente un objeto de un tipo a otro, la clase concreta subyacente del objeto que tiene, debe heredar de la clase a la que está intentando convertirlo, incluso si ambos completan lo mismo interfaz.

Piénselo, los dos objetos tienen que tener en común para implementar la misma interfaz que es el mismo subconjunto de firmas de métodos. Es posible que no tengan (probablemente no tengan) las mismas propiedades o campos de datos.

¿no funcionaría esto?

class MyClass : ICloneable
{
public MyClass()
{

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

return mc;
}

Solo tiene que llamar a: 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);
   }

Me gustó lo siguiente y funciona muy bien para convertir de un objeto a otro usando el operador implícito:

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top