Пример #1
0
        private void GenerateCollector(ILGenerator il, Type classType,
                                       DataField f,
                                       MethodInfo getValueMethod,
                                       MethodInfo addToListMethod,
                                       MethodInfo addRepLevelMethod,
                                       TypeConversion conversion)
        {
            //arg 0 - collection of classes, clr objects
            //arg 1 - data items (typed list)
            //arg 2 - repetitions (optional)
            //arg 3 - max repetition level

            //make collection a local variable
            LocalBuilder collection = il.DeclareLocal(classType);

            il.Emit(Ldarg_0);
            il.Emit(Stloc, collection.LocalIndex);

            using (il.ForEachLoop(classType, collection, out LocalBuilder currentElement))
            {
                if (f.IsArray)
                {
                    //reset repetition level to 0
                    LocalBuilder rl = il.DeclareLocal(typeof(int));
                    il.Emit(Ldc_I4_0);
                    il.StLoc(rl);

                    //currentElement is a nested array in this case
                    LocalBuilder array = il.DeclareLocal(typeof(object));

                    //get array and put into arrayElement
                    il.Emit(Ldloc, currentElement.LocalIndex);
                    il.Emit(Callvirt, getValueMethod);
                    il.Emit(Stloc, array.LocalIndex);

                    //enumerate this array
                    using (il.ForEachLoop(f.ClrNullableIfHasNullsType, array, out LocalBuilder arrayElement))
                    {
                        //store in destination list
                        il.CallVirt(addToListMethod, Ldarg_1, arrayElement);

                        //add repetition level
                        il.CallVirt(addRepLevelMethod, Ldarg_2, rl);

                        //set repetition level to max
                        il.Emit(Ldarg_3);
                        il.StLoc(rl);
                    }
                }
                else
                {
                    //hold item
                    LocalBuilder item = il.DeclareLocal(f.ClrNullableIfHasNullsType);

                    //get current value, converting if necessary
                    il.Emit(Ldloc, currentElement.LocalIndex);
                    il.Emit(Callvirt, getValueMethod);
                    if (conversion != null)
                    {
                        conversion.Emit(il);
                    }
                    il.Emit(Stloc, item.LocalIndex);

                    //store in destination list
                    il.Emit(Ldarg_1);
                    il.Emit(Ldloc, item.LocalIndex);
                    il.Emit(Callvirt, addToListMethod);
                }
            }

            il.Emit(Ldc_I4_0);
            il.Emit(Ret);
        }
Пример #2
0
        private void GenerateAssigner(ILGenerator il, Type classType, DataField field,
                                      MethodInfo setValueMethod,
                                      MethodInfo getDataMethod,
                                      MethodInfo getRepsMethod,
                                      TypeConversion conversion)
        {
            //arg 0 - DataColumn
            //arg 1 - class intances array (Array)

            if (field.IsArray)
            {
                LocalBuilder repItem = il.DeclareLocal(typeof(int));
                LocalBuilder dce     = il.DeclareLocal(typeof(DataColumnEnumerator));

                //we will use DataColumnEnumerator for complex types

                //create an instance of it
                il.Emit(Ldarg_0); //constructor argument
                il.Emit(Newobj, typeof(DataColumnEnumerator).GetTypeInfo().DeclaredConstructors.First());
                il.StLoc(dce);

                LocalBuilder ci            = il.DeclareLocal(typeof(int)); //class index
                LocalBuilder classInstance = il.DeclareLocal(classType);   //class instance

                using (il.ForEachLoopFromEnumerator(typeof(object), dce, out LocalBuilder element))
                {
                    //element should be an array for simple repeatables

                    //get class instance by index
                    il.GetArrayElement(Ldarg_1, ci, true, typeof(Array), classInstance);

                    //assign data item to class property
                    il.CallVirt(setValueMethod, classInstance, element);

                    il.Increment(ci);
                }
            }
            else
            {
                //get values
                LocalBuilder data = il.DeclareLocal(typeof(Array));
                il.CallVirt(getDataMethod, Ldarg_0);
                il.StLoc(data);

                //get length of values
                LocalBuilder dataLength = il.DeclareLocal(typeof(int));
                il.GetArrayLength(data, dataLength);

                LocalBuilder dataItem  = il.DeclareLocal(field.ClrNullableIfHasNullsType); //current value
                bool         dataIsRef = field.HasNulls && !field.ClrNullableIfHasNullsType.IsSystemNullable();

                LocalBuilder classInstance = il.DeclareLocal(classType);

                using (il.ForLoop(dataLength, out LocalBuilder iData))
                {
                    //get data value
                    il.GetArrayElement(data, iData, dataIsRef, field.ClrNullableIfHasNullsType, dataItem);

                    //get class instance
                    il.GetArrayElement(Ldarg_1, iData, true, classType, classInstance);

                    il.LdLoc(classInstance);

                    //convert if necessary
                    if (conversion != null)
                    {
                        il.LdLoc(dataItem);
                        conversion.Emit(il);
                    }
                    else
                    {
                        il.Emit(Ldloc, dataItem.LocalIndex);
                    }

                    //assign data item to class property
                    il.Emit(Callvirt, setValueMethod);
                }
            }

            il.Emit(Ret);
        }