/// <summary> /// Generates IL to write a single value from the stack to the stream /// </summary> /// <param name="type">Type of the object on the stack</param> /// <param name="args">The generate args.</param> void GenerateWriteTypeIL(Type type, GenerateArgs args) { MethodInfo method = GetTypeMethod(type, TypeMethodType.Serialize); const string valueVar = "writeValue"; const string valueDoneLabel = "_writeValueDone"; DynamicMethodHelper il = args.il; bool dynamic = IsDynamic && (type.IsValueType == false); il.BeginScope(); { il.DeclareLocal(valueVar, type); il.PopLocalFromObject(valueVar); if (dynamic) { const string notNullLabel = "_dynamicNotNull"; // If value is a reference type then serialize // NullVersion (-1) and do nothing else. No need to // save a type name or anything. If not null then // add type to name table and write the type byte // before calling serializer to write the instance il.PushLocal(valueVar); il.GotoIfTrue(notNullLabel); il.PushLocal(args.streamVar); il.PushInt(-1); il.CallMethod(GetTypeMethod(typeof(byte), TypeMethodType.Serialize)); il.Goto(valueDoneLabel); il.MarkLabel(notNullLabel); // push writer for Write(byte) call il.PushLocal(args.streamVar); // push nameTable for Add(Type) call il.DebugWriteNamedLocal(args.nameTableVar); il.PushLocal(args.nameTableVar); // push (object)value // call object.GetType() il.PushLocal(valueVar); il.Cast(typeof(object)); il.CallMethod(typeof(object).GetMethod("GetType")); // push this.Version il.PushInt(this.Version); // call TypeNameTable.Add(Type, version) il.CallMethod(typeof(TypeNameTable).GetMethod("Add", new [] { typeof(Type), typeof(int) })); // Return type byte // call IPrimitiveWriter.Write(byte) il.CallMethod(GetTypeMethod(typeof(byte), TypeMethodType.Serialize)); } if (method.DeclaringType == typeof(IPrimitiveWriter)) { // push IPrimitiveWriter ; arg 1 for method call // push elemValue ; arg 2 for method call il.PushLocal(args.streamVar); il.PushLocal(valueVar); } else { // push value // push TypeSerializationArgs il.PushLocal(valueVar); il.PushArg(args.dataArg); } il.CallMethod(method); if (dynamic) { il.MarkLabel(valueDoneLabel); } } il.EndScope(); }