English 中文(简体)
Automapper, generics, dto funtimes
原标题:

Here s the deal:

I have a report designer where users can create reports based on some predefined datasets. They can select a set of columns to include in the report and then, when the report is ran, an IList is created by mapping the NHibernate collection over to the dto class collection using automapper.

The problem with this is that the DTO collection has a load of redundant columns in as it will be populated with all the data regardless of whether or not it s needed.

My solution to this? 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 properties needed:

#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);

The problem?

var dto =
                Mapper.Map<IList<MainInvoiceDataSums>, IList<generetedType>>(r);

We can t new up an IList using the generated type as the generic parameter :s

I seem to always run into problems like this. Am I abusing generics? Is this possible? It would make the app a lot faster (once caching and some checks to dissalow the temp assembly to be regenerated etc are added) and a lot less fussy to maintain.

w://

We can t ne up an IList using the generated type as the generic parameter :s

I seem to always run into problems like this. Am I abusing generics? Is this possible? It would make the app a lot faster (once caching and some checks to dissalow the temp assembly to be regenerated etc are added) and a lot less fussy to maintain.

w://

最佳回答

got it!!

dont call createmap passing the generic lists!

MethodInfo createMap = createMapInfo.MakeGenericMethod(new Type[] { typeof(MainInvoiceDataSums), generetedType });

sorted!!

:)

w://

问题回答

Why not use the non-generic version of Map?

Mapper.Map(r, typeof(IList<MainInvoiceDataSums>), 
                       typeof(IList<>).MakeGenericType(new [] { generatedType });




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签