dimanche 8 février 2015

How to store a mapping between a type A and a run-time Func type transformation?

Runtime Mapping objects of type A into a similar type A`




  1. List of types is discovered run-time using System.Reflection




  2. An expression Expression<Func<object, object>> is made for each appropriate Type. The function converts object of type oldType into an object of newType.






Sidenote:


The generic type arguments for the Func<object, object> are somewhat-misleading, it feels like it should be Func<newType,oldType>, but the types are not known compile-time:



Expression<Func<object, object>> GetConvertExpression(Type oldType, Type newType)





  1. The expressions are compiled and stored into a Dictionary<Type, Func<object, object>>




Question - How to solve the downsides of the current approach?



  1. A dictionary lookup is necessary to convert an object. I had thought of baking in a big if/then/else or case statment into a big unified Expression, this would should work well with a small number of types.

  2. Unnecessary casting operations within the generated IL.

  3. Argument and return type of the generated code is of type object. This basically ensures that there will be casting operations all around. Especially when a large transformation of List<oldType> to List<newType> has to be performed.




Generated IL:



object convert(object oldInst)
{
newType newInst = newType();
oldType oldInstCast = (oldType)oldInst;
newInst.field1 = oldInstCast.field1;
.......
// note: if some field of oldInst has a type in the DICTIONARY and
// it's value is not null, we have to perform the convert
// operation recursively for that field
if(oldInstCast.field3 != null)
{
// Type of the field was determined when this code was generated
// And it is known that the dictionary will contain it
Func<object, object> transformFun = dictionary[typeof(oldFieldType)];
newInst.field3 = (newFieldType)transformFun(oldInstCast.field3);
}

newInst.fieldz = oldInstCast.fieldz;

return newInst;
}





Aucun commentaire:

Enregistrer un commentaire