I am currently building an object model for HL7 messages. Without diving into those, the basic structure that we have looks similar to this:
- Base Object
- Intermediary Object
- DeepMessage1
- DeepMessage2
- Message1
- Message2
- Intermediary Object
I want to have a deep copy/clone that will copy all of the similar properties from DeepMessage1 to DeepMessage2 or Message1 or Message2.
public class BaseObject
{
PersonName Name; //A personName includes a first name and last name.
}
public class IntermediaryObject : BaseObject
{
Accident accident; //An accident codes and a description.
}
public class Message1 : BaseObject
{
//this class doesn't actually contain any special handling, just used for
//easy understanding for the API
}
public class Message2 : BaseObject
{
DateTime AdmissionDate; //Note the admission date is also contained in
//DeepMessage1, but not DeepMessage2
}
public class DeepMessage1 : IntermediaryObject
{
DateTime AdmissionDate; //Note this property is also contained in Message2 and
//needs to be copied
}
public class DeepMessage2 : IntermediaryObject
{
DateTime DischargeDate;
}
With that structure in mind, I want to be able to create a deep copy of every property that one object shares with another. This other question was a really good start, but ultimately I couldn't use reflection as that was shallow cloning, and serialization requires the exact same object.
I ended up with this code, but it only performs a shallow copy.
public T Copy<T>() where T : new()
{
T destination = new T();
if (destination is HL7Message)
{
foreach (var destinationProperty in destination.GetType().GetProperties())
{
foreach (var sourceProperty in this.GetType().GetProperties())
{
if (destinationProperty.Name.Equals(sourceProperty.Name))
{
destinationProperty.SetValue(destination, destinationProperty.GetValue(this, null), null);
}
}
}
return destination;
}
else
{
throw new InvalidOperationException("The destination copy type is not an HL7Message object");
}
}
I was hoping that in my if (destinationProperty.Name.Equals(sourceProperty.Name))
block I could attempt to call Copy on any properties that are of a specific base type (which all of the objects in my library extend). However, I couldn't get the Copy in that section to work as I can't determine the T at runtime.
Do I just need to have a separate type of Copy for the specific objects and have the Messages use the Copy or is there a way to do this that is so damn crazy?