Question

Supposons que j'ai deux classes avec la même interface:

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

class SomeClass : ISomeInterface {}

class SomeOtherClass : ISomeInterface {}

Supposons que j'ai une instance d'ISomeInterface qui représente une SomeClass. Existe-t-il un moyen simple de copier cela dans une nouvelle instance de SomeOtherClass sans copier manuellement chaque membre?

UPDATE: Pour mémoire, je <<> n'essaye pas d'essayer de convertir l'instance de SomeClass en instance de SomeOtherClass. Ce que j'aimerais faire est quelque chose comme ceci:

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

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

Je ne veux simplement pas avoir à le faire à la main car ces objets ont beaucoup de propriétés.

Était-ce utile?

La solution

"Pourriez-vous me donner un exemple de ce que je peux faire (ou du moins m'indiquer les bonnes méthodes à utiliser)? Je ne semble pas pouvoir les trouver sur MSDN " & # 8211; Jason Baker

Jason, quelque chose comme ce qui suit:

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

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

Je suggérerais d'écrire un outil pour cracher le code dont vous avez besoin pour un constructeur de copie, plutôt que de le réfléchir de manière réfléchie au moment de l'exécution - ce qui serait moins performant.

Autres conseils

Vous pouvez créer des opérateurs implicites dans chaque classe pour effectuer la conversion pour vous:

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
}

puis SomeOtherClass soc = sc; et vice-versa fonctionneraient.

N’est-ce pas le but d’une interface de ne pas avoir à faire cela? Faites-vous quelque chose avec la mise en œuvre concrète de SomeOtherClass? Au lieu d’utiliser l’implémentation concrète, utilisez l’interface et peu importe si vous utilisez la classe SomeClass ou SomeOther.

En dehors de cela, le mieux que vous puissiez faire est d'écrire une sorte de fonction d'assistance (vous devez toujours le faire manuellement ou regarder dans la réflexion) qui copie chaque propriété sur l'interface qui ressemble à ceci:

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

Cependant, mon premier réflexe serait de dire: éloignez-vous de la mise en œuvre et concentrez-vous sur votre interface. Dans ce cas, peu importe ce qui se cache en dessous.

Reflection ... parcourt chaque propriété et la définit sur la propriété correspondante de l'autre objet.

Découvrez la réponse de Joe pour la solution Reflection.

Je suppose que vous utilisez Visual Studio.

Connaissez-vous les raccourcis Ctrl + Maj + r et Ctrl + Maj + p? Sinon, ctrl + Maj + r commence / termine l'enregistrement d'une macro de frappe. Ctrl + Maj + P lit la macro enregistrée.

Ce que j'ai fait lorsque j'ai défini beaucoup de propriétés, c'est de copier les déclarations de propriétés là où je veux qu'elles soient définies et d'enregistrer une macro pour transformer la déclaration en une instruction set et déplacer le curseur à la ligne suivante. , je joue alors jusqu’à ce que toutes les instructions soient terminées.

Non, pour convertir (convertir) en transparence un objet d'un type à un autre, la classe concrète sous-jacente de l'objet que vous possédez doit hériter de la classe à laquelle vous essayez de le convertir, même si les deux implémentent le même interface.

Pensez-y, tous les deux objets doivent avoir en commun pour implémenter la même interface est le même sous-ensemble de signatures de méthode. Ils n’auront peut-être pas (probablement pas) les mêmes propriétés ou les mêmes champs de données.

ça ne marcherait pas?

class MyClass : ICloneable
{
public MyClass()
{

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

return mc;
}

Vous devez seulement appeler: 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);
   }

J'ai aimé ce qui suit et ça marche très bien de convertir un objet en un autre en utilisant un opérateur implicite:

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;
        }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top