Вот сделка:
У меня есть дизайнер отчетов, в котором пользователи могут создавать отчеты на основе некоторых предопределенных наборов данных. Они могут выбрать набор столбцов для включения в отчет, а затем, когда отчет запускается, создается IList путем сопоставления коллекции NHibernate с коллекцией классов dto с помощью automapper.
Проблема заключается в том, что в коллекции DTO загружены избыточные столбцы, поскольку в нее будут включены все данные независимо от того, нужны они или нет.
Мое решение этого? Почему бы не создать тип DTO во время выполнения, используя имеющуюся у нас информацию, и сопоставить коллекцию nhibernate с динамически создаваемой коллекцией DTO, используя только необходимые свойства:
#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");
// create a new type builder
TypeBuilder typeBuilder = module.DefineType("ReportDto", TypeAttributes.Public | TypeAttributes.Class);
foreach (var propertyName in propNames)
{
// Generate a private field
FieldBuilder field = typeBuilder.DefineField("_" + propertyName, typeof(string), FieldAttributes.Private);
// Generate a public property
PropertyBuilder property =
typeBuilder.DefineProperty(propertyName,
PropertyAttributes.None,
typeof(string),
new Type[] { typeof(string) });
// The property set and property get methods require a special set of attributes:
MethodAttributes GetSetAttr =
MethodAttributes.Public |
MethodAttributes.HideBySig;
// Define the "get" accessor method for current private field.
MethodBuilder currGetPropMthdBldr =
typeBuilder.DefineMethod("get_value",
GetSetAttr,
typeof(string),
Type.EmptyTypes);
// Intermediate Language stuff...
ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);
// Define the "set" accessor method for current private field.
MethodBuilder currSetPropMthdBldr =
typeBuilder.DefineMethod("set_value",
GetSetAttr,
null,
new Type[] { typeof(string) });
// Again some Intermediate Language stuff...
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);
// Last, we must map the two methods created above to our PropertyBuilder to
// their corresponding behaviors, "get" and "set" respectively.
property.SetGetMethod(currGetPropMthdBldr);
property.SetSetMethod(currSetPropMthdBldr);
}
Type generetedType = typeBuilder.CreateType();
// Now we have our type. Let's create an instance from it:
object generetedObject = Activator.CreateInstance(generetedType);
#endregion
Mapper.CreateMap(typeof(MainInvoiceDataSums), generetedType);
var dto =
Mapper.Map<IList<MainInvoiceDataSums>, IList<generetedType>>(r);
Проблема?
var dto =
Mapper.Map<IList<MainInvoiceDataSums>, IList<generetedType>>(r);
Мы не можем создать новый IList, используя сгенерированный тип в качестве универсального параметра: s
Кажется, я всегда сталкиваюсь с такими проблемами. Я злоупотребляю дженериками? Это возможно? Это сделало бы приложение намного быстрее (после добавления кеширования и некоторых проверок, чтобы отключить временную сборку, которая будет регенерирована и т. Д.) И намного менее суетливым в обслуживании.
ш: //
Мы не можем создать IList, используя сгенерированный тип в качестве универсального параметра: s
Кажется, я всегда сталкиваюсь с такими проблемами. Я злоупотребляю дженериками? Это возможно? Это сделало бы приложение намного быстрее (после добавления кеширования и некоторых проверок для исключения временной сборки, которая будет регенерирована и т. Д.) И намного менее суетливым в обслуживании.
ш: //