For performance reasons I cannot use Automapper or any other convention based mapping tool. Ideally I would like one method signature that we can call... e.g. - mapper.Map<,>() however the following isn't valid syntax
public MyModelView Map<Tin, Tout>(Tin source)
where Tin: MyModelDto
where Tout: MyModelView
{
return new MyModelView{
Prop1 = source.Prop1;
};
}
public MyModelDto Map<Tin, Tout>(Tin source)
where Tin: MyModelView
where Tout: MyModelDto
{
return new MyModelDto {
Prop1 = source.Prop1;
};
}
One solution that works but I personally find ugly is the following.
public void Map(MyModelDto source, out MyModelView outParam)
{
outParam = new MyModelView();
outParam.Prop1 = source.Prop1;
}
public void Map(MyModelView source, out MyModelDto outParam)
{
outParam = new MyModelDto ();
outParam.Prop1 = source.Prop1;
}
MyModelDto myDto = new MyModelDto { Prop1 = "Hello World" };
MyModelView myView;
mapper.Map(myDto, out myView);
My question is, is there any way to force a definite type without using reflection or an out param to force uniqueness or is the out param method the cleanest approach I'm going to get?
UPDATE: So I have made a solution that satisfies my need, it utilizes the RuntimeTypeHandle which is not completely ideal but it works for me and causes the least dev pain for use. If my requirements only had allowed for 1 type conversion per object I would have stuck with a simpler solution. For completeness...here is what I've come up with.
credit for the type handling idea: What is quicker, switch on string or elseif on type?
public class Mapper : IMapper
{
private delegate object TypeHandler(Object node, Type desiredReturn);
private static readonly Dictionary<RuntimeTypeHandle, TypeHandler> TypeLibrary = CreateTypeHandler();
private static Dictionary<RuntimeTypeHandle, TypeHandler> CreateTypeHandler()
{
var ret = new Dictionary<RuntimeTypeHandle, TypeHandler>();
ret[typeof(MyModelDto).TypeHandle] = HandleMyModelDto;
//ret[typeof (Jill).TypeHandle] = HandleJill;
//ret[typeof (Marko).TypeHandle] = HandleMarko;
return ret;
}
private static object HandleMyModelDto(object source, Type desiredMapping)
{
MyModelDto sourceObj = source as MyModelDto;
if (desiredMapping == typeof(MyModelView))
{
return new MyModelView { Prop1 = sourceObj.Prop1 };
}
else if (desiredMapping == typeof (MyModelBusiness))
{
return new MyModelBusiness { Prop1 = sourceObj.Prop1 };
}
}
public Tout Map<Tin, Tout>(Tin source)
{
TypeHandler handler;
if (TypeLibrary.TryGetValue(Type.GetTypeHandle(source), out handler))
{
return (Tout)handler(source, typeof(Tout));
}
else
{
//Unexpected type...
throw new NotImplementedException("Type mapping not implemented");
}
}
}
and consumption is as follows
Mapper mapper = new Mapper();
MyModelDto myDto = new MyModelDto { Prop1 = "Hello World" };
MyModelView returnVal = mapper.Map<MyModelDto, MyModelView>(myDto);