I feel that one of the short-comings in C# is the lack of default copy constructors for classes and, to add to my frustration, the help provided in MSDN about this topic just doesn't cut it. I decided to implement my own "generic" copy constructor, which is by no means feature-complete, but certainly delivers what I need now.
UPDATE 2008 SEP 23: I've updated the copy mechanism in this article. Rather use it than the example in this code.
To start off, I've created a test class.
public class Foo
{
public string Alias { get; set; }
public Guid Id { get; set; }
public int Rating { get; set; }
}
Now, I need to add a constructor to Foo that'll accept another instance of Foo.
public Foo (Foo source){}
According to the MSDN article metioned above, round about here is when you start coding manual assignment statements for every single property that your object has. Instead of that, I've made use of reflection to get and set property values.(Exception handling/parameter checking excluded for code-clarity purposes)
public Foo (Foo source)
{
PropertyInfo[] propertyInfos = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var propertyInfo in propertyInfos)
{
propertyInfo.SetValue(this, propertyInfo.GetValue(source, null), null);
}
}
What this code is doing is getting information about all the properties in the class that are public and instance variables. It then loops through them, getting the values from the object passed in, and setting them on the destination object, which in this case is "this".
Because this code is type-agnostic, I then refactored it out to a static method in a seperate class as follows:
public static void CopyObjectValues<T> (T source, T destination)
{
PropertyInfo[] propertyInfos = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var propertyInfo in propertyInfos)
{
propertyInfo.SetValue(destination, propertyInfo.GetValue(source, null), null);
}
}
...and modified the copy constructor to look like this:
public Foo (Foo source)
{
ObjectUtilities.CopyObjectValues(source, this);
}
You can now use this static method in an class that you need to implement your own copy constructor on.