Here's the deal:
I have a report designer where users can create reports based on specific predefined datasets. They can select a set of columns to include in the report, and then, when the report is run, an IList is created by mapping the NHibernate collection to the dto-class collection using automapper.
The problem is that the DTO collection has a load of redundant columns, because it will be filled with all the data, whether it is needed or not.
My decision? Why not create a DTO type at runtime using the information we have and map the nhibernate collection to the dynamically created DTO collection using only the necessary properties:
#region create a dto type:
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "tmpAssembly";
var assemblyBuilder = System.Threading.Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder module = assemblyBuilder.DefineDynamicModule("tmpModule");
TypeBuilder typeBuilder = module.DefineType("ReportDto", TypeAttributes.Public | TypeAttributes.Class);
foreach (var propertyName in propNames)
{
FieldBuilder field = typeBuilder.DefineField("_" + propertyName, typeof(string), FieldAttributes.Private);
PropertyBuilder property =
typeBuilder.DefineProperty(propertyName,
PropertyAttributes.None,
typeof(string),
new Type[] { typeof(string) });
MethodAttributes GetSetAttr =
MethodAttributes.Public |
MethodAttributes.HideBySig;
MethodBuilder currGetPropMthdBldr =
typeBuilder.DefineMethod("get_value",
GetSetAttr,
typeof(string),
Type.EmptyTypes);
ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);
MethodBuilder currSetPropMthdBldr =
typeBuilder.DefineMethod("set_value",
GetSetAttr,
null,
new Type[] { typeof(string) });
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);
property.SetGetMethod(currGetPropMthdBldr);
property.SetSetMethod(currSetPropMthdBldr);
}
Type generetedType = typeBuilder.CreateType();
object generetedObject = Activator.CreateInstance(generetedType);
#endregion
Mapper.CreateMap(typeof(MainInvoiceDataSums), generetedType);
var dto =
Mapper.Map<IList<MainInvoiceDataSums>, IList<generetedType>>(r);
Problem?
var dto =
Mapper.Map<IList<MainInvoiceDataSums>, IList<generetedType>>(r);
IList : s
, . ? ? ( , , , ..) .
://
IList, : s
, . ? ? ( , , , ..) .
://