Sometimes you want to cast between two types that share the same parent. In one of my resent cases I had two settings objects which shared a parent and I wanted to create a second object from the first and keep the parent data.
Take the following code:
record Parent {
public string Surname { get; init; }
public string Location { get; init; }
}
record Son : Parent {
public string Forename { get; init; }
}
record Daughter : Parent {
public int Age { get; init; }
}
Say you had a Son
object and wanted it to be a Daughter
and keep the Surname
and Location
from Parent
. You would have to map the fields manually. Fine if you have the one instance of this behaviour with one set of objects, but what if you want to do this repeatedly using different types? I had an ever increasing set of cases where I wanted to move data between object types whilst keeping parent data, so I wrote this method:
public static class ObjectExtensions
{
public static TChild CastToTypeWithParentProperties<TParent, TChild>(this TParent source) where TChild : TParent, new()
{
if (source is null)
{
throw new ArgumentNullException(nameof(source), "Source object cannot be null");
}
var parentType = typeof(TParent);
var properties = parentType.GetProperties().Where(property => property is {CanRead: true, CanWrite: true});
var target = new TChild();
foreach (var prop in properties)
{
var value = prop.GetValue(source);
prop.SetValue(target, value);
}
return target;
}
}
This allows you to do var daughter = son.CastToTypeWithParentProperties<Parent, Daughter>(parent);
and daugher
would share the same Surname
and Location
values as son
.