0

Delphi has a standard mechanism where one object can be copied from another, paraphrased here as:

class Persistent 
{
    protected AssignError(Persistent source)
    {
       throw new ConvertError("Cannot assign a {0} to a {1}", source.GetType().Name, this.GetType().Name);
    }

    protected virtual AssignTo(Persistent destination)
    {
        destination.AssignError(this);
    }

    public virtual Assign(Persistent source)
    {
       source.AssignTo(this);
    }
}

Does the .NET FCL has a canonical syntax of copying objects between each other?

e.g.:

interface IPersistent
{
   public virtual Assign(Object source);
}

public class User : IPersistent
{
    private Image avatarThumbnail;
    private String name;

    public override Assign(Object source)
    {
       if (source is User)
       {
          this.avatarThumbnail = source.avatarThumbnail;
          this.name = source.Name;
       }
       else if (source is Image)
           avatarThumbnail = (Image)source;
       else if (source is DirectoryEntry)
           name = ((DirectoryEntry) source).Firstname + " " + ((DirectoryEntry) source).Lastname;
       else
           throw new AssignError("Assign from {0}", source.GetType());
    }
}

Yes i just invented a standard IPersistent interface; but is there already a mechanism to copy objects between each other?

Update

Note: i am talking about the opposite of cloning an object.

User originalUser = new User();
User theClone = originalUser.Clone();
theClone.Lastname = "Guyer";

originalUser.Assign(theClone);

Or, i don't even need to have a clone at all:

User u = new User();
u.Assign(salesOrder); //copy name/e-mail from the sales order

or

SalesOrder s = new SalesOrder();
s.SalesOrderDate = DateTime.Now;
User customer = new Customer("Kirsten");
s.Assign(user); //copy sold-to/ship-to information from the user
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • are you doing this in VS or using Prism inside Delphi 2010 – MethodMan Dec 21 '11 at 20:34
  • It depends - are you expecting these functions to be called automatically when an assignment statement is encountered? (a la C++ copy constructors) - if so, the answer is no. – Damien_The_Unbeliever Dec 21 '11 at 20:36
  • @Damien_The_Unbeliever No, calling `databaseConnection.Assign(font)` would work fine (keeping in mind that i'll be writing the logic that knows how to copy a Font into a DatabaseConnection) – Ian Boyd Dec 21 '11 at 21:50

2 Answers2

2

The .NET framework has the ICloneable interface:

Supports cloning, which creates a new instance of a class with the same value as an existing instance.

And:

The ICloneable interface contains one member, Clone, which is intended to support cloning beyond that supplied by MemberwiseClone. For more information about cloning, deep versus shallow copies, and examples, see the Object.MemberwiseClone method.


Update:

As far as I know, there is nothing equivalent to what you want (standard way to copy some values between different objects) in the BCL.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • Note that the spec allows `Clone` to be implemented as either a deep copy or a shallow copy. So, be careful when using an `ICloneable` provided by others. – Brian Dec 21 '11 at 20:39
  • Odd that you refer to the `ICloneable` interface, since it is [useless and considered obsolete](http://blogs.msdn.com/b/brada/archive/2004/05/03/125427.aspx). The Framework Design Guidelines advice against anyone using it. It has no advantage over a `Clone` method on an object that doesn't implement `ICloneable`. – Steven Dec 21 '11 at 20:39
  • 1
    @Steven - The MSDN documentation does not mention that it is obsolete. It is also the closest thing to what the OP is asking for. – Oded Dec 21 '11 at 20:42
  • i wasn't referring to cloning an object, since strictly speaking this system allows cloning a `DbConnection` into a `System.Drawing.Font`. – Ian Boyd Dec 21 '11 at 21:48
  • @Oded: What does the `ICloneable` interface exactly do? It's just an interface; you have to implement cloning yourself and in that case it doesn't add any value over implementing a `Clone` method without that interface. If you advice the OP to use `ICloneable`, you are basically saying 'create a clone method yourself`, which doesn't really help him :-). btw I didn't say `ICloneable` is marked with the `ObsoleteAttribute`, but it is considered to be obsolete, since the Framework Design Guidelines advice against using it. – Steven Dec 22 '11 at 08:53
  • @Steven - fair enough. But if you read the comments from the OP, is looks like that's not what he is after, and for what he _does_ want, he is happy to write his own methods. – Oded Dec 22 '11 at 08:55
0

As an alternative to the standard ICloneable interface, you could perform the copy of public properties/fields using reflection. Here's some code written off the top of my head for doing so:

foreach(PropertyInfo mbr in src.GetType().GetProperties())
    mbr.SetValue(dst, src.GetValue(src, BindingFlags.GetProperty, null, null, null), BindingFlags.SetProperty, null, null, null)

foreach(FieldInfo mbr in src.GetType().GetFields())
    mbr.SetValue(dst, src.GetValue(src, BindingFlags.GetField, null, null, null), BindingFlags.SetField, null, null, null)
M.Babcock
  • 18,753
  • 6
  • 54
  • 84
  • i already have cloning (http://stackoverflow.com/a/78612/12597). The issue now is to copy the clone back into the original. – Ian Boyd Dec 21 '11 at 21:49
  • How is this any better than using [`MemberwiseClone`](http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx) ? – Brian Dec 22 '11 at 14:11
  • @Brian - In a lot of ways it isn't. 'MemberwiseClone' is a native implementation of a similar process. The only benefit I've found of implementing it myself is in niche situations where I need control over which fields are copied and to what depth. Not really relevant to the original question here though. – M.Babcock Dec 22 '11 at 14:36