tags:

views:

110

answers:

3

Forgive the dumb newby question but... I'm moving data from one table to another. The destination table schema is identical to the source table except it has a few extra columns. Linq to SQL generates classes to represent each of these tables. If I have a source object, how do I create a destination object from it? E.g., source object has properties A,B,C. Destination object has A,B,C,X,Y. I want to do something like:

  Destination dest = new Destination(Source source, int x, int y)
  {
    this.X = x;
    this.Y = y;
    ...
    // somehow set all the destination properties to 
    // their corresponding source value
  }

Is there an elegant way to do this other than explicity setting each of the properties? Can I make Destination inherit from Source somehow? Would that help?

+1  A: 

If the types are unrelated, MiscUtil has:

Destination dest = PropertyCopy<Destination>.CopyFrom(source);

then set manually:

dest.X = x;
dest.Y = y;

You could alternatively write a conversion method / operator, but you'll need to maintain it (PropertyCopy is automatic).


Re your inheritance point; I don't think that fits well here; you could do something with the partial class, but it won't work with LINQ-to-SQL any more if you do (it handles inheritance itself, and won't love you doing this).

Marc Gravell
A: 

You could use copy constructors in your objects where you pass in the source and manually copy the fields of it to the destination. This does however require a lot of manual coding.

You could also use a library like AutoMapper to do this for you automatically. You define that source can map to destination (nothing more than that), and it works it out for you based on the names of items.

Alternatively, if you are purely just moving data around (I'm assuming in a database), could you just use pure SQL to do it without the need for any code?

adrianbanks
+1  A: 

Why couldn't you write your own auto conversion utilizing Reflection? You can do something to the tune of

   class Program {
     static void Main(string[] args)
     {
       Source item1 = new Source(2, 3, 4);
       Destination item2 = new Destination(item1, ContinueCopy);

       Console.WriteLine(string.Format("X: {0}\n Y: {1}", item2.X, item2.Y));
       Console.ReadKey();
     }

     public static bool ContinueCopy(string name, Type type)
     {
        if (name == "X" && type == typeof(int)) return false;

        return true;
     }
  }

  public class Source {
     public Source() { }
     public Source(int x, int y, int z)
     {
       myX = x;
       myY = y;
       myZ = z;
     }
     private int myX;
     public int X
     {
       get { return myX; }
       set { myX = value; }
     }

     private int myY;
     public int Y
     {
       get { return myY; }
       set { myY = value; }
     }

     private int myZ;
     public int Z
     {
       get { return myZ; }
       set { myZ = value; }
     }
  }


  public class Destination {
     public delegate bool ContinueCopyCallback(string propertyName, Type propertyType);

     public Destination() : this(0,0) { }
     public Destination(int x, int y)
     {
        myX = x;
        myY = y;
     }
     public Destination(Source copy) : this(copy, null) { }
     public Destination(Source copy, ContinueCopyCallback callback)
     {
        foreach (PropertyInfo pi in copy.GetType().GetProperties())
        {
           PropertyInfo pi2 = this.GetType().GetProperty(pi.Name);
           if ((callback == null || (callback != null && callback(pi.Name, 
              pi.PropertyType))) && pi2 != null && pi2.GetType() == pi.GetType())
           {
              pi2.SetValue(this, pi.GetValue(copy, null), null);
           }
        }
     }

     private int myX;
     public int X
     {
        get { return myX; }
        set { myX = value; }
     }

     private int myY;
     public int Y
     {
        get { return myY; }
        set { myY = value; }
     }
 }

The output will give item2.X the value of 2 and item2.Y the value of 3.

You can also provide the ability to have a callback which could allow you to custom filter on property names you do not wish to automatically copy. As well you could write the copy code as a shallow copy Constructor for Destination that accepts Source as a parameter.

This is a lightweight method given your needs are as simple as presented.

Jamie Altizer