Search code examples
c#.netshallow-copy

Copying objects to 'this' object in C#


I have a certain hirerchy of classes that needs the capeability to copy all public properties from one object to another.
Each class has a certain set of public properties that might differ from any other class.

Example:

class Base
{
  // Common properties/methods...
  public void Copy<T>(T data) where T : Base
  {
     // ...
  }
}

class D1 : Base
{
  public int ID
  {
    get;
    set;
  }
}

class D2 : Base
{
  public string Name
  {
    get;
    set;
  }
}

Through googling I have read about those methods:

  • Using reflection
  • Generating IL code
  • Serialization

All of them are either very complex or very slow or sometimes both.
Am I missing something? Is there any other way to access the raw this pointer?

EDIT:
I will clerify.
T is of the type of the calling class. For example if it was called by D1 T will always be D1.
The reason for the generic is that I can't really know what T is.
Am I missing something?
Should I just use Base data as the parameter?


Solution

  • The Copy method in the Base class only has access to the properties that are defined in the Base class. You can copy these properties.

    But you cannot copy the properties from the subclasses without using something like reflection. But even with reflection you need some kind of knowledge about the mapping of the properties between different subclasses, like copying the ID property to Name.

    So you'll need to write separate implementations for each (allowed) subclass conversion.

    public interface IBaseCopier<TFrom, TTo> where TFrom : Base, TTo : Base
    {
      void Copy(TFrom from, TTo to);
    }
    
    public class D1ToD2Copier : IBaseCopier<D1, D2>
    {
      public void Copy(D1 from, D2 to)
      {
        // Copy properties from the D1 instance to the D2 instance.
      }
    }
    

    You can register all the ICopier<TFrom, TTo> implementations in a factory class. This class will look up the implementation of the copier, based on the type arguments. If there is no copier for a certain type combination, i.e. the conversion is not supported, the factory should throw an exception.

    public class CopierFactory
    {
      public ICopier<TFrom, TTo> Create<TFrom, TTo>() where TFrom : Base, TTo : Base
      {
        // Look up the ICopier implementation for the given types.
      }
    }
    

    Edit

    You can use the MemberwiseClone method to create a copy of an object.

    public class Base
    {
      public static T Copy<T>(T data) where T : Base
      {
        return data.MemberwiseClone() as T;
      }
    }
    

    If you need more control over the cloning, you can implement the ICloneable interface.

    Note: You should realize that you cannot clone a D1 instance into a D2 instance. That would be like cloning a sheep into a horse.