Exemplo n.º 1
0
        //DataReader로 부터 값들을 읽어 인스턴스를 만든다
        private ConstructInstance CreateConstructInstance(IDataReader reader)
        {
            ParameterException.Check(reader != null, ParameterError.NotExistReader);
            var   type          = typeof(T);
            var   dynamicMethod = new DynamicMethod("ConstructInstance", type, new[] { typeof(IDataReader) }, type);
            var   il            = dynamicMethod.GetILGenerator();
            Label startLoop     = il.DefineLabel();
            Label endLoop       = il.DefineLabel();

            ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);

            il.Emit(OpCodes.Newobj, constructor); //[instance]
            il.MarkLabel(startLoop);

            PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo property in properties)
            {
                Label startValueTypeNullLoop = il.DefineLabel();
                Label endValueTypeNullLoop   = il.DefineLabel();
                Label jumpToEnd = il.DefineLabel();

                var columnAttribute = property.GetCustomAttribute <ColumnAttribute>();
                AttributeException.Check(columnAttribute != null, AttributeError.NotExistColumnAttribute);
                var columnName = columnAttribute.Name ?? property.Name;
                //SetValue
                il.Emit(OpCodes.Dup);               //[instance][instance]
                il.Emit(OpCodes.Ldarg_0);           //[instance][instance][IDataReader]
                il.Emit(OpCodes.Ldstr, columnName); //[instance][instance][IDataReader][Name]
                il.Emit(OpCodes.Call,
                        typeof(IDataReaderHelper).GetMethod(nameof(IDataReaderHelper
                                                                   .GetValue))); //[instance][instance][value]
                il.Emit(OpCodes.Dup);                                            //[instance][instance][value][value]
                il.Emit(OpCodes.Ldsfld,
                        typeof(DBNull).GetField(nameof(DBNull.Value)));          //[instance][instance][value][value][DBNullValue]
                il.Emit(OpCodes.Ceq);                                            // [instance][instance][value][result]
                il.Emit(OpCodes.Brtrue, startValueTypeNullLoop);                 //[instance][instance]
                if (property.PropertyType.IsValueType)
                {
                    il.Emit(OpCodes.Unbox_Any, property.PropertyType); //[instance][instance][unbox_value]
                }
                il.MarkLabel(endValueTypeNullLoop);
                il.Emit(OpCodes.Call, property.GetSetMethod()); //[instance]
                il.Emit(OpCodes.Br, jumpToEnd);

                il.MarkLabel(startValueTypeNullLoop);
                if (property.PropertyType.IsValueType)
                {
                    il.Emit(OpCodes.Pop);      //[instance][instance]
                    il.Emit(OpCodes.Ldc_I4_0); //[instance][instance][0]
                }

                il.Emit(OpCodes.Br, endValueTypeNullLoop);
                il.MarkLabel(jumpToEnd);
            }

            il.MarkLabel(endLoop);
            il.Emit(OpCodes.Ret);
            return((ConstructInstance)dynamicMethod.CreateDelegate(typeof(ConstructInstance)));
        }