예제 #1
0
        private void EmitReadValueNotNullMethod(ILGenerator gen,
                                                TypeInformation typeInformation)
        {
            Action loadReader           = () => gen.Emit(OpCodes.Ldarg_0);
            Action loadSerializer       = () => gen.Emit(OpCodes.Ldarg_1);
            Action loadRemotingEndPoint = () => gen.Emit(OpCodes.Ldarg_2);

            MethodInfo method;

            if (IsSingleton(typeInformation.Type, out method))
            {
                EmitReadSingleton(gen, method);
            }
            else if (EmitReadNativeType(gen,
                                        loadReader,
                                        loadSerializer,
                                        loadRemotingEndPoint,
                                        typeInformation.Type,
                                        false))
            {
            }
            else if (typeInformation.IsArray)
            {
                EmitReadArray(gen,
                              loadReader,
                              loadSerializer,
                              loadRemotingEndPoint,
                              typeInformation);
            }
            else if (typeInformation.IsCollection)
            {
                EmitReadCollection(gen,
                                   loadReader,
                                   loadSerializer,
                                   loadRemotingEndPoint,
                                   typeInformation);
            }
            else if (typeInformation.IsStack)
            {
                EmitReadStack(gen,
                              loadReader,
                              loadSerializer,
                              loadRemotingEndPoint,
                              typeInformation);
            }
            else if (typeInformation.IsQueue)
            {
                EmitReadQueue(gen,
                              loadReader,
                              loadSerializer,
                              loadRemotingEndPoint,
                              typeInformation);
            }
            else
            {
                LocalBuilder value = gen.DeclareLocal(typeInformation.Type);
                EmitReadCustomType(gen,
                                   loadReader,
                                   loadSerializer,
                                   loadRemotingEndPoint,
                                   typeInformation,
                                   value);
            }

            gen.Emit(OpCodes.Ret);
        }
예제 #2
0
        private void EmitReadArray(ILGenerator gen,
                                   Action loadReader,
                                   Action loadSerializer,
                                   Action loadRemotingEndPoint,
                                   TypeInformation typeInformation)
        {
            var elementType = typeInformation.ElementType;

            var value = gen.DeclareLocal(typeInformation.Type);
            var count = gen.DeclareLocal(typeof(int));
            var i     = gen.DeclareLocal(typeof(int));

            // count = reader.ReadInt32()
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Call, Methods.ReadInt32);
            gen.Emit(OpCodes.Stloc, count);

            // value = new XXX[count]
            gen.Emit(OpCodes.Ldloc, count);
            gen.Emit(OpCodes.Newarr, elementType);
            gen.Emit(OpCodes.Stloc, value);

            var loop = gen.DefineLabel();
            var end  = gen.DefineLabel();

            // int i = 0
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Stloc, i);

            // loop:
            gen.MarkLabel(loop);
            // if (i < count) goto end
            gen.Emit(OpCodes.Ldloc, i);
            gen.Emit(OpCodes.Ldloc, count);
            gen.Emit(OpCodes.Clt);
            gen.Emit(OpCodes.Brfalse, end);

            // value[i] = <ReadValue>
            gen.Emit(OpCodes.Ldloc, value);
            gen.Emit(OpCodes.Ldloc, i);

            EmitReadValue(gen,
                          loadReader,
                          loadSerializer,
                          loadRemotingEndPoint,
                          elementType);

            gen.Emit(OpCodes.Stelem, elementType);

            // ++i
            gen.Emit(OpCodes.Ldloc, i);
            gen.Emit(OpCodes.Ldc_I4_1);
            gen.Emit(OpCodes.Add);
            gen.Emit(OpCodes.Stloc, i);
            // goto loop
            gen.Emit(OpCodes.Br, loop);

            // end:
            gen.MarkLabel(end);
            gen.Emit(OpCodes.Ldloc, value);
        }
예제 #3
0
        private void EmitWriteArray(ILGenerator gen,
                                    TypeInformation typeInformation,
                                    Action loadWriter,
                                    Action loadValue,
                                    Action loadSerializer,
                                    Action loadRemotingEndPoint,
                                    ArrayOrder order = ArrayOrder.Forward)
        {
            var elementType = typeInformation.ElementType;
            var length      = gen.DeclareLocal(typeof(int));
            var i           = gen.DeclareLocal(typeof(int));
            var loop        = gen.DefineLabel();
            var end         = gen.DefineLabel();

            // writer.Write(value.Length)
            loadValue();
            gen.Emit(OpCodes.Ldlen);
            gen.Emit(OpCodes.Stloc, length);

            loadWriter();
            gen.Emit(OpCodes.Ldloc, length);
            gen.Emit(OpCodes.Call, Methods.WriteInt32);

            // i = 0
            // OR
            // i = length-1
            switch (order)
            {
            case ArrayOrder.Forward:
                gen.Emit(OpCodes.Ldc_I4_0);
                gen.Emit(OpCodes.Stloc, i);
                break;

            case ArrayOrder.Reverse:
                gen.Emit(OpCodes.Ldloc, length);
                gen.Emit(OpCodes.Ldc_I4_1);
                gen.Emit(OpCodes.Sub);
                gen.Emit(OpCodes.Stloc, i);
                break;

            default:
                throw new InvalidEnumArgumentException(nameof(order), (int)order, typeof(ArrayOrder));
            }

            gen.MarkLabel(loop);

            // while i != length
            // OR
            // while i != -1

            switch (order)
            {
            case ArrayOrder.Forward:
                gen.Emit(OpCodes.Ldloc, length);
                gen.Emit(OpCodes.Ldloc, i);
                gen.Emit(OpCodes.Ceq);
                gen.Emit(OpCodes.Brtrue, end);
                break;

            default:
                gen.Emit(OpCodes.Ldc_I4_0);
                gen.Emit(OpCodes.Ldloc, i);
                gen.Emit(OpCodes.Cgt);
                gen.Emit(OpCodes.Brtrue, end);
                break;
            }

            Action loadCurrentValue = () =>
            {
                loadValue();
                gen.Emit(OpCodes.Ldloc, i);
                gen.Emit(OpCodes.Ldelem, elementType);
            };
            Action loadCurrentValueAddress = () =>
            {
                loadValue();
                gen.Emit(OpCodes.Ldloc, i);
                gen.Emit(OpCodes.Ldelema, elementType);
            };

            EmitWriteValue(gen,
                           loadWriter,
                           loadCurrentValue,
                           loadCurrentValueAddress,
                           loadSerializer,
                           loadRemotingEndPoint,
                           elementType);

            switch (order)
            {
            case ArrayOrder.Forward:
                gen.Emit(OpCodes.Ldloc, i);
                gen.Emit(OpCodes.Ldc_I4_1);
                gen.Emit(OpCodes.Add);
                gen.Emit(OpCodes.Stloc, i);
                break;

            default:
                gen.Emit(OpCodes.Ldloc, i);
                gen.Emit(OpCodes.Ldc_I4_1);
                gen.Emit(OpCodes.Sub);
                gen.Emit(OpCodes.Stloc, i);
                break;
            }

            // goto loop
            gen.Emit(OpCodes.Br, loop);

            gen.MarkLabel(end);
        }
예제 #4
0
        private void EmitReadCustomType(ILGenerator gen,
                                        Action loadReader,
                                        Action loadSerializer,
                                        Action loadRemotingEndPoint,
                                        TypeInformation type,
                                        LocalBuilder target)
        {
            if (type.Type.GetCustomAttribute <DataContractAttribute>() != null)
            {
                CreateAndStoreNewInstance(gen, type, target);
                EmitCallBeforeDeserialization(gen, type, target);
                EmitReadAllFields(gen,
                                  loadReader,
                                  loadSerializer,
                                  loadRemotingEndPoint,
                                  type,
                                  target);
                EmitReadAllProperties(gen,
                                      loadReader,
                                      loadSerializer,
                                      loadRemotingEndPoint,
                                      type,
                                      target);
                EmitCallAfterDeserialization(gen, type, target);
                gen.Emit(OpCodes.Ldloc, target);
            }
            else if (type.Type.GetRealCustomAttribute <ByReferenceAttribute>(true) != null)
            {
                var proxyInterface = FindProxyInterface(type.Type);

                var objectRetrieved  = gen.DefineLabel();
                var getOrCreateProxy = gen.DefineLabel();

                // The stream contains a hint for us as to whether we should create a proxy OR retrieve the actual subject
                // for the given grain-id.
                loadReader();
                gen.Emit(OpCodes.Callvirt, Methods.ReadByte);
                gen.Emit(OpCodes.Ldc_I4, (int)ByReferenceHint.RetrieveSubject);
                gen.Emit(OpCodes.Ceq);
                gen.Emit(OpCodes.Brfalse_S, getOrCreateProxy);
                // result = _remotingEndPoint.RetrieveSubject(serializer.ReadLong())
                var retrieveSubject = typeof(IRemotingEndPoint).GetMethod("RetrieveSubject").MakeGenericMethod(proxyInterface);
                loadRemotingEndPoint();
                loadReader();
                gen.Emit(OpCodes.Callvirt, Methods.ReadLong);
                gen.Emit(OpCodes.Callvirt, retrieveSubject);
                gen.Emit(OpCodes.Br, objectRetrieved);


                gen.MarkLabel(getOrCreateProxy);
                // result = _remotingEndPoint.GetExistingOrCreateNewProxy<T>(serializer.ReadLong());
                var getOrCreateNewProxy = typeof(IRemotingEndPoint).GetMethod("GetExistingOrCreateNewProxy").MakeGenericMethod(proxyInterface);
                loadRemotingEndPoint();
                loadReader();
                gen.Emit(OpCodes.Callvirt, Methods.ReadLong);
                gen.Emit(OpCodes.Callvirt, getOrCreateNewProxy);

                gen.Emit(OpCodes.Stloc, target);
                gen.Emit(OpCodes.Ldloc, target);

                gen.MarkLabel(objectRetrieved);
            }
            else
            {
                throw new NotImplementedException();
            }
        }