コード例 #1
0
ファイル: ObjectTypeDescriptor.cs プロジェクト: yardee/BTDB
        public void GenerateLoad(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushCtx,
                                 Action <IILGen> pushDescriptor, Type targetType)
        {
            if (targetType == typeof(object))
            {
                var resultLoc  = ilGenerator.DeclareLocal(typeof(DynamicObject), "result");
                var labelNoCtx = ilGenerator.DefineLabel();
                ilGenerator
                .Do(pushDescriptor)
                .Castclass(typeof(ObjectTypeDescriptor))
                .Newobj(typeof(DynamicObject).GetConstructor(new[] { typeof(ObjectTypeDescriptor) }) !)
                .Stloc(resultLoc)
                .Do(pushCtx)
                .BrfalseS(labelNoCtx)
                .Do(pushCtx)
                .Ldloc(resultLoc)
                .Callvirt(() => default(ITypeBinaryDeserializerContext).AddBackRef(null))
                .Mark(labelNoCtx);
                var idx = 0;
                foreach (var pair in _fields)
                {
                    var idxForCapture = idx;
                    ilGenerator.Ldloc(resultLoc);
                    ilGenerator.LdcI4(idx);
                    pair.Value.GenerateLoadEx(ilGenerator, pushReader, pushCtx,
                                              il =>
                                              il.Do(pushDescriptor)
                                              .LdcI4(idxForCapture)
                                              .Callvirt(() => default(ITypeDescriptor).NestedType(0)), typeof(object),
                                              _typeSerializers.ConvertorGenerator);
                    ilGenerator.Callvirt(() => default(DynamicObject).SetFieldByIdxFast(0, null));
                    idx++;
                }

                ilGenerator
                .Ldloc(resultLoc)
                .Castclass(typeof(object));
            }
            else
            {
                var resultLoc          = ilGenerator.DeclareLocal(targetType, "result");
                var labelNoCtx         = ilGenerator.DefineLabel();
                var defaultConstructor = targetType.GetConstructor(Type.EmptyTypes);
                if (defaultConstructor == null)
                {
                    ilGenerator
                    .Ldtoken(targetType)
                    .Call(() => Type.GetTypeFromHandle(new RuntimeTypeHandle()))
                    .Call(() => RuntimeHelpers.GetUninitializedObject(null))
                    .Castclass(targetType);
                }
                else
                {
                    ilGenerator
                    .Newobj(defaultConstructor);
                }

                ilGenerator
                .Stloc(resultLoc)
                .Do(pushCtx)
                .BrfalseS(labelNoCtx)
                .Do(pushCtx)
                .Ldloc(resultLoc)
                .Callvirt(() => default(ITypeBinaryDeserializerContext).AddBackRef(null))
                .Mark(labelNoCtx);
                var props = targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                for (var idx = 0; idx < _fields.Count; idx++)
                {
                    var idxForCapture = idx;
                    var pair          = _fields[idx];
                    var prop          = props.FirstOrDefault(p => GetPersistentName(p) == pair.Key);
                    if (prop == null || !_typeSerializers.IsSafeToLoad(prop.PropertyType))
                    {
                        pair.Value.GenerateSkipEx(ilGenerator, pushReader, pushCtx);
                        continue;
                    }

                    ilGenerator.Ldloc(resultLoc);
                    pair.Value.GenerateLoadEx(ilGenerator, pushReader, pushCtx,
                                              il => il.Do(pushDescriptor).LdcI4(idxForCapture)
                                              .Callvirt(() => default(ITypeDescriptor).NestedType(0)),
                                              prop.PropertyType, _typeSerializers.ConvertorGenerator);
                    ilGenerator.Callvirt(prop.GetAnySetMethod() !);
                }

                ilGenerator.Ldloc(resultLoc);
            }
        }