private void WriteStructMethod(StructMapping mapping) { string methodName = (string)MethodNames[mapping]; ilg = new CodeGenerator(this.typeBuilder); List<Type> argTypes = new List<Type>(5); List<string> argNames = new List<string>(5); argTypes.Add(typeof(string)); argNames.Add("n"); argTypes.Add(typeof(string)); argNames.Add("ns"); argTypes.Add(mapping.TypeDesc.Type); argNames.Add("o"); if (mapping.TypeDesc.IsNullable) { argTypes.Add(typeof(Boolean)); argNames.Add("isNullable"); } argTypes.Add(typeof(Boolean)); argNames.Add("needType"); ilg.BeginMethod(typeof(void), GetMethodBuilder(methodName), argTypes.ToArray(), argNames.ToArray(), CodeGenerator.PrivateMethodAttributes); if (mapping.TypeDesc.IsNullable) { ilg.If(ilg.GetArg("o"), Cmp.EqualTo, null); { ilg.If(ilg.GetArg("isNullable"), Cmp.EqualTo, true); { MethodInfo XmlSerializationWriter_WriteNullTagLiteral = typeof(XmlSerializationWriter).GetMethod( "WriteNullTagLiteral", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldarg("n"); ilg.Ldarg("ns"); ilg.Call(XmlSerializationWriter_WriteNullTagLiteral); } ilg.EndIf(); ilg.GotoMethodEnd(); } ilg.EndIf(); } ilg.If(ilg.GetArg("needType"), Cmp.NotEqualTo, true); // if (!needType) LocalBuilder tLoc = ilg.DeclareLocal(typeof(Type), "t"); MethodInfo Object_GetType = typeof(object).GetMethod( "GetType", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ArgBuilder oArg = ilg.GetArg("o"); ilg.LdargAddress(oArg); ilg.ConvertAddress(oArg.ArgType, typeof(object)); ilg.Call(Object_GetType); ilg.Stloc(tLoc); WriteTypeCompare("t", mapping.TypeDesc.Type); // Bool on the stack from WriteTypeCompare. ilg.If(); // if (t == typeof(...)) WriteDerivedTypes(mapping); if (mapping.TypeDesc.IsRoot) WriteEnumAndArrayTypes(); ilg.Else(); if (mapping.TypeDesc.IsRoot) { MethodInfo XmlSerializationWriter_WriteTypedPrimitive = typeof(XmlSerializationWriter).GetMethod( "WriteTypedPrimitive", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String), typeof(Object), typeof(Boolean) } ); ilg.Ldarg(0); ilg.Ldarg("n"); ilg.Ldarg("ns"); ilg.Ldarg("o"); ilg.Ldc(true); ilg.Call(XmlSerializationWriter_WriteTypedPrimitive); ilg.GotoMethodEnd(); } else { MethodInfo XmlSerializationWriter_CreateUnknownTypeException = typeof(XmlSerializationWriter).GetMethod( "CreateUnknownTypeException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(Object) } ); ilg.Ldarg(0); ilg.Ldarg(oArg); ilg.ConvertValue(oArg.ArgType, typeof(Object)); ilg.Call(XmlSerializationWriter_CreateUnknownTypeException); ilg.Throw(); } ilg.EndIf(); // if (t == typeof(...)) ilg.EndIf(); // if (!needType) if (!mapping.TypeDesc.IsAbstract) { if (mapping.TypeDesc.Type != null && typeof(XmlSchemaObject).IsAssignableFrom(mapping.TypeDesc.Type)) { MethodInfo XmlSerializationWriter_set_EscapeName = typeof(XmlSerializationWriter).GetMethod( "set_EscapeName", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(Boolean) } ); ilg.Ldarg(0); ilg.Ldc(false); ilg.Call(XmlSerializationWriter_set_EscapeName); } string xmlnsSource = null; MemberMapping[] members = TypeScope.GetAllMembers(mapping, memberInfos); int xmlnsMember = FindXmlnsIndex(members); if (xmlnsMember >= 0) { MemberMapping member = members[xmlnsMember]; CodeIdentifier.CheckValidIdentifier(member.Name); xmlnsSource = RaCodeGen.GetStringForMember("o", member.Name, mapping.TypeDesc); } ilg.Ldarg(0); ilg.Ldarg("n"); ilg.Ldarg("ns"); ArgBuilder argO = ilg.GetArg("o"); ilg.Ldarg(argO); ilg.ConvertValue(argO.ArgType, typeof(Object)); ilg.Ldc(false); if (xmlnsSource == null) ilg.Load(null); else { System.Diagnostics.Debug.Assert(xmlnsSource.StartsWith("o.@", StringComparison.Ordinal)); ILGenLoad(xmlnsSource); } MethodInfo XmlSerializationWriter_WriteStartElement = typeof(XmlSerializationWriter).GetMethod( "WriteStartElement", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String), typeof(Object), typeof(Boolean), typeof(XmlSerializerNamespaces) } ); ilg.Call(XmlSerializationWriter_WriteStartElement); if (!mapping.TypeDesc.IsRoot) { ilg.If(ilg.GetArg("needType"), Cmp.EqualTo, true); { MethodInfo XmlSerializationWriter_WriteXsiType = typeof(XmlSerializationWriter).GetMethod( "WriteXsiType", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldstr(GetCSharpString(mapping.TypeName)); ilg.Ldstr(GetCSharpString(mapping.Namespace)); ilg.Call(XmlSerializationWriter_WriteXsiType); } ilg.EndIf(); } for (int i = 0; i < members.Length; i++) { MemberMapping m = members[i]; if (m.Attribute != null) { CodeIdentifier.CheckValidIdentifier(m.Name); if (m.CheckShouldPersist) { ilg.LdargAddress(oArg); ilg.Call(m.CheckShouldPersistMethodInfo); ilg.If(); } if (m.CheckSpecified != SpecifiedAccessor.None) { string memberGet = RaCodeGen.GetStringForMember("o", m.Name + "Specified", mapping.TypeDesc); ILGenLoad(memberGet); ilg.If(); } WriteMember(RaCodeGen.GetSourceForMember("o", m, mapping.TypeDesc, ilg), m.Attribute, m.TypeDesc, "o"); if (m.CheckSpecified != SpecifiedAccessor.None) { ilg.EndIf(); } if (m.CheckShouldPersist) { ilg.EndIf(); } } } for (int i = 0; i < members.Length; i++) { MemberMapping m = members[i]; if (m.Xmlns != null) continue; CodeIdentifier.CheckValidIdentifier(m.Name); bool checkShouldPersist = m.CheckShouldPersist && (m.Elements.Length > 0 || m.Text != null); if (checkShouldPersist) { ilg.LdargAddress(oArg); ilg.Call(m.CheckShouldPersistMethodInfo); ilg.If(); } if (m.CheckSpecified != SpecifiedAccessor.None) { string memberGet = RaCodeGen.GetStringForMember("o", m.Name + "Specified", mapping.TypeDesc); ILGenLoad(memberGet); ilg.If(); } string choiceSource = null; if (m.ChoiceIdentifier != null) { CodeIdentifier.CheckValidIdentifier(m.ChoiceIdentifier.MemberName); choiceSource = RaCodeGen.GetStringForMember("o", m.ChoiceIdentifier.MemberName, mapping.TypeDesc); } WriteMember(RaCodeGen.GetSourceForMember("o", m, m.MemberInfo, mapping.TypeDesc, ilg), choiceSource, m.ElementsSortedByDerivation, m.Text, m.ChoiceIdentifier, m.TypeDesc, true); if (m.CheckSpecified != SpecifiedAccessor.None) { ilg.EndIf(); } if (checkShouldPersist) { ilg.EndIf(); } } WriteEndElement("o"); } ilg.EndMethod(); }
internal void GenerateSupportedTypes(Type[] types, TypeBuilder serializerContractTypeBuilder) { ilg = new CodeGenerator(serializerContractTypeBuilder); ilg.BeginMethod( typeof(bool), "CanSerialize", new Type[] { typeof(Type) }, new string[] { "type" }, CodeGenerator.PublicOverrideMethodAttributes); var uniqueTypes = new HashSet<Type>(); for (int i = 0; i < types.Length; i++) { Type type = types[i]; if (type == null) continue; if (!type.GetTypeInfo().IsPublic && !type.GetTypeInfo().IsNestedPublic) continue; if (!uniqueTypes.Add(type)) continue; // DDB172141: Wrong generated CS for serializer of List<string> type if (type.GetTypeInfo().IsGenericType || type.GetTypeInfo().ContainsGenericParameters) continue; ilg.Ldarg("type"); ilg.Ldc(type); ilg.If(Cmp.EqualTo); { ilg.Ldc(true); ilg.GotoMethodEnd(); } ilg.EndIf(); } ilg.Ldc(false); ilg.GotoMethodEnd(); ilg.EndMethod(); }
private string GenerateTypeElement(XmlTypeMapping xmlTypeMapping) { ElementAccessor element = xmlTypeMapping.Accessor; TypeMapping mapping = element.Mapping; string methodName = NextMethodName(element.Name); ilg = new CodeGenerator(this.typeBuilder); ilg.BeginMethod( typeof(void), methodName, new Type[] { typeof(object) }, new string[] { "o" }, CodeGenerator.PublicMethodAttributes ); MethodInfo XmlSerializationWriter_WriteStartDocument = typeof(XmlSerializationWriter).GetMethod( "WriteStartDocument", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_WriteStartDocument); ilg.If(ilg.GetArg("o"), Cmp.EqualTo, null); if (element.IsNullable) { WriteLiteralNullTag(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : "")); } else WriteEmptyTag(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : "")); ilg.GotoMethodEnd(); ilg.EndIf(); if (!mapping.TypeDesc.IsValueType && !mapping.TypeDesc.Type.GetTypeInfo().IsPrimitive) { MethodInfo XmlSerializationWriter_TopLevelElement = typeof(XmlSerializationWriter).GetMethod( "TopLevelElement", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_TopLevelElement); } WriteMember(new SourceInfo("o", "o", null, typeof(object), ilg), null, new ElementAccessor[] { element }, null, null, mapping.TypeDesc, true); ilg.EndMethod(); return methodName; }