void WriteQualifiedNameElement(string name, string ns, object defaultValue, SourceInfo source, bool nullable, TypeMapping mapping) { bool hasDefault = defaultValue != null && defaultValue != DBNull.Value; if (hasDefault) { throw CodeGenerator.NotSupported("XmlQualifiedName DefaultValue not supported. Fail in WriteValue()"); } List<Type> argTypes = new List<Type>(); ilg.Ldarg(0); ilg.Ldstr(name); argTypes.Add(typeof(string)); if (ns != null) { ilg.Ldstr(ns); argTypes.Add(typeof(string)); } source.Load(mapping.TypeDesc.Type); argTypes.Add(mapping.TypeDesc.Type); MethodInfo XmlSerializationWriter_WriteXXX = typeof(XmlSerializationWriter).GetMethod( nullable ? ("WriteNullableQualifiedNameLiteral") : "WriteElementQualifiedName", CodeGenerator.InstanceBindingFlags, null, argTypes.ToArray(), null ); ilg.Call(XmlSerializationWriter_WriteXXX); if (hasDefault) { throw CodeGenerator.NotSupported("XmlQualifiedName DefaultValue not supported. Fail in WriteValue()"); } }
public override bool Equals(object obj) { if (obj == null) { return(Source == null); } SourceInfo info = obj as SourceInfo; if (info != null) { return(Source == info.Source); } return(false); }
internal void ILGenLoad(string source, Type type) { if (source.StartsWith("o.@", StringComparison.Ordinal)) { System.Diagnostics.Debug.Assert(memberInfos.ContainsKey(source.Substring(3))); MemberInfo memInfo = memberInfos[source.Substring(3)]; ilg.LoadMember(ilg.GetVariable("o"), memInfo); if (type != null) { Type memType = (memInfo is FieldInfo) ? ((FieldInfo)memInfo).FieldType : ((PropertyInfo)memInfo).PropertyType; ilg.ConvertValue(memType, type); } } else { SourceInfo info = new SourceInfo(source, null, null, null, ilg); info.Load(type); } }
internal void WriteInstanceOf(SourceInfo source, Type type, CodeGenerator ilg) { { source.Load(typeof(object)); ilg.IsInst(type); ilg.Load(null); ilg.Cne(); return; } }
internal void WriteLocalDecl(string variableName, SourceInfo initValue) { Type localType = initValue.Type; LocalBuilder localA = initValue.ILG.DeclareOrGetLocal(localType, variableName); if (initValue.Source != null) { if (initValue == "null") { initValue.ILG.Load(null); } else { if (initValue.Arg.StartsWith("o.@", StringComparison.Ordinal)) { Debug.Assert(initValue.MemberInfo != null); Debug.Assert(initValue.MemberInfo.Name == initValue.Arg.Substring(3)); initValue.ILG.LoadMember(initValue.ILG.GetLocal("o"), initValue.MemberInfo); } else if (initValue.Source.EndsWith("]", StringComparison.Ordinal)) { initValue.Load(initValue.Type); } else if (initValue.Source == "fixup.Source" || initValue.Source == "e.Current") { String[] vars = initValue.Source.Split('.'); object fixup = initValue.ILG.GetVariable(vars[0]); PropertyInfo propInfo = initValue.ILG.GetVariableType(fixup).GetProperty(vars[1]); initValue.ILG.LoadMember(fixup, propInfo); initValue.ILG.ConvertValue(propInfo.PropertyType, localA.LocalType); } else { object sVar = initValue.ILG.GetVariable(initValue.Arg); initValue.ILG.Load(sVar); initValue.ILG.ConvertValue(initValue.ILG.GetVariableType(sVar), localA.LocalType); } } initValue.ILG.Stloc(localA); } }
private void WriteInstanceOf(SourceInfo source, Type type) { RaCodeGen.WriteInstanceOf(source, type, ilg); }
private void WriteArrayLocalDecl(string typeName, string variableName, SourceInfo initValue, TypeDesc arrayTypeDesc) { RaCodeGen.WriteArrayLocalDecl(typeName, variableName, initValue, arrayTypeDesc); }
private void WriteAttribute(SourceInfo source, AttributeAccessor attribute, string parent) { if (attribute.Mapping is SpecialMapping) { SpecialMapping special = (SpecialMapping)attribute.Mapping; if (special.TypeDesc.Kind == TypeKind.Attribute || special.TypeDesc.CanBeAttributeValue) { System.Diagnostics.Debug.Assert(parent == "o" || parent == "p"); MethodInfo XmlSerializationWriter_WriteXmlAttribute = typeof(XmlSerializationWriter).GetMethod( "WriteXmlAttribute", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(XmlNode), typeof(Object) } ); ilg.Ldarg(0); ilg.Ldloc(source.Source); ilg.Ldarg(parent); ilg.ConvertValue(ilg.GetArg(parent).ArgType, typeof(Object)); ilg.Call(XmlSerializationWriter_WriteXmlAttribute); } else throw new InvalidOperationException(SR.XmlInternalError); } else { TypeDesc typeDesc = attribute.Mapping.TypeDesc; source = source.CastTo(typeDesc); WritePrimitive("WriteAttribute", attribute.Name, attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : "", attribute.Default, source, attribute.Mapping, false, false, false); } }
void WriteLocalDecl(string variableName, SourceInfo initValue) { RaCodeGen.WriteLocalDecl(variableName, initValue); }
private void WriteElement(SourceInfo source, ElementAccessor element, string arrayName, bool writeAccessor) { string name = writeAccessor ? element.Name : element.Mapping.TypeName; string ns = element.Any && element.Name.Length == 0 ? null : (element.Form == XmlSchemaForm.Qualified ? (writeAccessor ? element.Namespace : element.Mapping.Namespace) : ""); if (element.Mapping is NullableMapping) { if (source.Type == element.Mapping.TypeDesc.Type) { MethodInfo Nullable_get_HasValue = element.Mapping.TypeDesc.Type.GetMethod( "get_HasValue", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); source.LoadAddress(element.Mapping.TypeDesc.Type); ilg.Call(Nullable_get_HasValue); } else { source.Load(null); ilg.Load(null); ilg.Cne(); } ilg.If(); string fullTypeName = element.Mapping.TypeDesc.BaseTypeDesc.CSharpName; SourceInfo castedSource = source.CastTo(element.Mapping.TypeDesc.BaseTypeDesc); ElementAccessor e = element.Clone(); e.Mapping = ((NullableMapping)element.Mapping).BaseMapping; WriteElement(e.Any ? source : castedSource, e, arrayName, writeAccessor); if (element.IsNullable) { ilg.Else(); WriteLiteralNullTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""); } ilg.EndIf(); } else if (element.Mapping is ArrayMapping) { ArrayMapping mapping = (ArrayMapping)element.Mapping; if (element.IsUnbounded) { throw Globals.NotSupported("Unreachable: IsUnbounded is never set true!"); } else { ilg.EnterScope(); string fullTypeName = mapping.TypeDesc.CSharpName; WriteArrayLocalDecl(fullTypeName, arrayName, source, mapping.TypeDesc); if (element.IsNullable) { WriteNullCheckBegin(arrayName, element); } else { if (mapping.TypeDesc.IsNullable) { ilg.Ldloc(ilg.GetLocal(arrayName)); ilg.Load(null); ilg.If(Cmp.NotEqualTo); } } WriteStartElement(name, ns, false); WriteArrayItems(mapping.ElementsSortedByDerivation, null, null, mapping.TypeDesc, arrayName, null); WriteEndElement(); if (element.IsNullable) { ilg.EndIf(); } else { if (mapping.TypeDesc.IsNullable) { ilg.EndIf(); } } ilg.ExitScope(); } } else if (element.Mapping is EnumMapping) { WritePrimitive("WriteElementString", name, ns, element.Default, source, element.Mapping, false, true, element.IsNullable); } else if (element.Mapping is PrimitiveMapping) { PrimitiveMapping mapping = (PrimitiveMapping)element.Mapping; if (mapping.TypeDesc == QnameTypeDesc) WriteQualifiedNameElement(name, ns, element.Default, source, element.IsNullable, mapping); else { string suffixRaw = mapping.TypeDesc.XmlEncodingNotRequired ? "Raw" : ""; WritePrimitive(element.IsNullable ? ("WriteNullableStringLiteral" + suffixRaw) : ("WriteElementString" + suffixRaw), name, ns, element.Default, source, mapping, false, true, element.IsNullable); } } else if (element.Mapping is StructMapping) { StructMapping mapping = (StructMapping)element.Mapping; string methodName = ReferenceMapping(mapping); #if DEBUG // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe if (methodName == null) throw new InvalidOperationException(SR.Format(SR.XmlInternalErrorMethod, mapping.TypeDesc.Name)); #endif List<Type> argTypes = new List<Type>(); ilg.Ldarg(0); ilg.Ldstr(GetCSharpString(name)); argTypes.Add(typeof(string)); ilg.Ldstr(GetCSharpString(ns)); argTypes.Add(typeof(string)); source.Load(mapping.TypeDesc.Type); argTypes.Add(mapping.TypeDesc.Type); if (mapping.TypeDesc.IsNullable) { ilg.Ldc(element.IsNullable); argTypes.Add(typeof(Boolean)); } ilg.Ldc(false); argTypes.Add(typeof(Boolean)); MethodBuilder methodBuilder = EnsureMethodBuilder(typeBuilder, methodName, CodeGenerator.PrivateMethodAttributes, typeof(void), argTypes.ToArray()); ilg.Call(methodBuilder); } else if (element.Mapping is SpecialMapping) { SpecialMapping mapping = (SpecialMapping)element.Mapping; TypeDesc td = mapping.TypeDesc; string fullTypeName = td.CSharpName; if (element.Mapping is SerializableMapping) { WriteElementCall("WriteSerializable", typeof(IXmlSerializable), source, name, ns, element.IsNullable, !element.Any); } else { // XmlNode, XmlElement Label ifLabel1 = ilg.DefineLabel(); Label ifLabel2 = ilg.DefineLabel(); source.Load(null); ilg.IsInst(typeof(XmlNode)); ilg.Brtrue(ifLabel1); source.Load(null); ilg.Load(null); ilg.Ceq(); ilg.Br(ifLabel2); ilg.MarkLabel(ifLabel1); ilg.Ldc(true); ilg.MarkLabel(ifLabel2); ilg.If(); WriteElementCall("WriteElementLiteral", typeof(XmlNode), source, name, ns, element.IsNullable, element.Any); ilg.Else(); MethodInfo XmlSerializationWriter_CreateInvalidAnyTypeException = typeof(XmlSerializationWriter).GetMethod( "CreateInvalidAnyTypeException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(Object) } ); ilg.Ldarg(0); source.Load(null); ilg.Call(XmlSerializationWriter_CreateInvalidAnyTypeException); ilg.Throw(); ilg.EndIf(); } } else { throw new InvalidOperationException(SR.XmlInternalError); } }
private void WritePrimitive(string method, string name, string ns, object defaultValue, SourceInfo source, TypeMapping mapping, bool writeXsiType, bool isElement, bool isNullable) { TypeDesc typeDesc = mapping.TypeDesc; bool hasDefault = defaultValue != null && !Globals.IsDBNullValue(defaultValue) && mapping.TypeDesc.HasDefaultSupport; if (hasDefault) { if (mapping is EnumMapping) { #if DEBUG // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe if (defaultValue.GetType() != typeof(string)) throw new InvalidOperationException(SR.Format(SR.XmlInternalErrorDetails, name + " has invalid default type " + defaultValue.GetType().Name)); #endif source.Load(mapping.TypeDesc.Type); string enumDefaultValue = null; if (((EnumMapping)mapping).IsFlags) { string[] values = ((string)defaultValue).Split(null); for (int i = 0; i < values.Length; i++) { if (values[i] == null || values[i].Length == 0) continue; if (i > 0) enumDefaultValue += ", "; enumDefaultValue += values[i]; } } else { enumDefaultValue = (string)defaultValue; } ilg.Ldc(Enum.Parse(mapping.TypeDesc.Type, enumDefaultValue, false)); ilg.If(Cmp.NotEqualTo); // " != " } else { WriteCheckDefault(source, defaultValue, isNullable); } } List<Type> argTypes = new List<Type>(); ilg.Ldarg(0); argTypes.Add(typeof(String)); ilg.Ldstr(GetCSharpString(name)); if (ns != null) { argTypes.Add(typeof(String)); ilg.Ldstr(GetCSharpString(ns)); } Type argType; if (mapping is EnumMapping) { WriteEnumValue((EnumMapping)mapping, source, out argType); argTypes.Add(argType); } else { WritePrimitiveValue(typeDesc, source, out argType); argTypes.Add(argType); } if (writeXsiType) { argTypes.Add(typeof(XmlQualifiedName)); ConstructorInfo XmlQualifiedName_ctor = typeof(XmlQualifiedName).GetConstructor( CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String) } ); ilg.Ldstr(GetCSharpString(mapping.TypeName)); ilg.Ldstr(GetCSharpString(mapping.Namespace)); ilg.New(XmlQualifiedName_ctor); } MethodInfo XmlSerializationWriter_method = typeof(XmlSerializationWriter).GetMethod( method, CodeGenerator.InstanceBindingFlags, argTypes.ToArray() ); ilg.Call(XmlSerializationWriter_method); if (hasDefault) { ilg.EndIf(); } }
private void WriteElements(SourceInfo source, string enumSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, string arrayName, bool writeAccessors, bool isNullable) { if (elements.Length == 0 && text == null) return; if (elements.Length == 1 && text == null) { TypeDesc td = elements[0].IsUnbounded ? elements[0].Mapping.TypeDesc.CreateArrayTypeDesc() : elements[0].Mapping.TypeDesc; if (!elements[0].Any && !elements[0].Mapping.TypeDesc.IsOptionalValue) source = source.CastTo(td); WriteElement(source, elements[0], arrayName, writeAccessors); } else { bool doEndIf = false; if (isNullable && choice == null) { source.Load(typeof(object)); ilg.Load(null); ilg.If(Cmp.NotEqualTo); doEndIf = true; } int anyCount = 0; ArrayList namedAnys = new ArrayList(); ElementAccessor unnamedAny = null; // can only have one bool wroteFirstIf = false; string enumTypeName = choice == null ? null : choice.Mapping.TypeDesc.FullName; for (int i = 0; i < elements.Length; i++) { ElementAccessor element = elements[i]; if (element.Any) { anyCount++; if (element.Name != null && element.Name.Length > 0) namedAnys.Add(element); else if (unnamedAny == null) unnamedAny = element; } else if (choice != null) { string fullTypeName = element.Mapping.TypeDesc.CSharpName; object enumValue; string enumFullName = enumTypeName + ".@" + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, out enumValue); if (wroteFirstIf) ilg.InitElseIf(); else { wroteFirstIf = true; ilg.InitIf(); } ILGenLoad(enumSource, choice == null ? null : choice.Mapping.TypeDesc.Type); ilg.Load(enumValue); ilg.Ceq(); if (isNullable && !element.IsNullable) { Label labelFalse = ilg.DefineLabel(); Label labelEnd = ilg.DefineLabel(); ilg.Brfalse(labelFalse); source.Load(typeof(object)); ilg.Load(null); ilg.Cne(); ilg.Br_S(labelEnd); ilg.MarkLabel(labelFalse); ilg.Ldc(false); ilg.MarkLabel(labelEnd); } ilg.AndIf(); WriteChoiceTypeCheck(source, fullTypeName, choice, enumFullName, element.Mapping.TypeDesc); SourceInfo castedSource = source; castedSource = source.CastTo(element.Mapping.TypeDesc); WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors); } else { TypeDesc td = element.IsUnbounded ? element.Mapping.TypeDesc.CreateArrayTypeDesc() : element.Mapping.TypeDesc; string fullTypeName = td.CSharpName; if (wroteFirstIf) ilg.InitElseIf(); else { wroteFirstIf = true; ilg.InitIf(); } WriteInstanceOf(source, td.Type); // WriteInstanceOf leave bool on the stack ilg.AndIf(); SourceInfo castedSource = source; castedSource = source.CastTo(td); WriteElement(element.Any ? source : castedSource, element, arrayName, writeAccessors); } } if (wroteFirstIf) { if (anyCount > 0) { // See "else " below if (elements.Length - anyCount > 0) { // NOOP } else ilg.EndIf(); } } if (anyCount > 0) { if (elements.Length - anyCount > 0) ilg.InitElseIf(); else ilg.InitIf(); string fullTypeName = typeof(XmlElement).FullName; source.Load(typeof(object)); ilg.IsInst(typeof(XmlElement)); ilg.Load(null); ilg.Cne(); ilg.AndIf(); LocalBuilder elemLoc = ilg.DeclareLocal(typeof(XmlElement), "elem"); source.Load(typeof(XmlElement)); ilg.Stloc(elemLoc); int c = 0; foreach (ElementAccessor element in namedAnys) { if (c++ > 0) ilg.InitElseIf(); else ilg.InitIf(); string enumFullName = null; Label labelEnd, labelFalse; if (choice != null) { object enumValue; enumFullName = enumTypeName + ".@" + FindChoiceEnumValue(element, (EnumMapping)choice.Mapping, out enumValue); labelFalse = ilg.DefineLabel(); labelEnd = ilg.DefineLabel(); ILGenLoad(enumSource, choice == null ? null : choice.Mapping.TypeDesc.Type); ilg.Load(enumValue); ilg.Bne(labelFalse); if (isNullable && !element.IsNullable) { source.Load(typeof(object)); ilg.Load(null); ilg.Cne(); } else { ilg.Ldc(true); } ilg.Br(labelEnd); ilg.MarkLabel(labelFalse); ilg.Ldc(false); ilg.MarkLabel(labelEnd); ilg.AndIf(); } labelFalse = ilg.DefineLabel(); labelEnd = ilg.DefineLabel(); MethodInfo XmlNode_get_Name = typeof(XmlNode).GetMethod( "get_Name", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); MethodInfo XmlNode_get_NamespaceURI = typeof(XmlNode).GetMethod( "get_NamespaceURI", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_Name); ilg.Ldstr(GetCSharpString(element.Name)); MethodInfo String_op_Equality = typeof(string).GetMethod( "op_Equality", CodeGenerator.StaticBindingFlags, new Type[] { typeof(string), typeof(string) } ); ilg.Call(String_op_Equality); ilg.Brfalse(labelFalse); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_NamespaceURI); ilg.Ldstr(GetCSharpString(element.Namespace)); ilg.Call(String_op_Equality); ilg.Br(labelEnd); ilg.MarkLabel(labelFalse); ilg.Ldc(false); ilg.MarkLabel(labelEnd); if (choice != null) ilg.If(); else ilg.AndIf(); WriteElement(new SourceInfo("elem", null, null, elemLoc.LocalType, ilg), element, arrayName, writeAccessors); if (choice != null) { ilg.Else(); MethodInfo XmlSerializationWriter_CreateChoiceIdentifierValueException = typeof(XmlSerializationWriter).GetMethod( "CreateChoiceIdentifierValueException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String), typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldstr(GetCSharpString(enumFullName)); ilg.Ldstr(GetCSharpString(choice.MemberName)); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_Name); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_NamespaceURI); ilg.Call(XmlSerializationWriter_CreateChoiceIdentifierValueException); ilg.Throw(); ilg.EndIf(); } } if (c > 0) { ilg.Else(); } if (unnamedAny != null) { WriteElement(new SourceInfo("elem", null, null, elemLoc.LocalType, ilg), unnamedAny, arrayName, writeAccessors); } else { MethodInfo XmlSerializationWriter_CreateUnknownAnyElementException = typeof(XmlSerializationWriter).GetMethod( "CreateUnknownAnyElementException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldloc(elemLoc); MethodInfo XmlNode_get_Name = typeof(XmlNode).GetMethod( "get_Name", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); MethodInfo XmlNode_get_NamespaceURI = typeof(XmlNode).GetMethod( "get_NamespaceURI", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Call(XmlNode_get_Name); ilg.Ldloc(elemLoc); ilg.Call(XmlNode_get_NamespaceURI); ilg.Call(XmlSerializationWriter_CreateUnknownAnyElementException); ilg.Throw(); } if (c > 0) { ilg.EndIf(); } } if (text != null) { string fullTypeName = text.Mapping.TypeDesc.CSharpName; if (elements.Length > 0) { ilg.InitElseIf(); WriteInstanceOf(source, text.Mapping.TypeDesc.Type); ilg.AndIf(); SourceInfo castedSource = source.CastTo(text.Mapping.TypeDesc); WriteText(castedSource, text); } else { SourceInfo castedSource = source.CastTo(text.Mapping.TypeDesc); WriteText(castedSource, text); } } if (elements.Length > 0) { if (isNullable) { ilg.InitElseIf(); source.Load(null); ilg.Load(null); ilg.AndIf(Cmp.NotEqualTo); } else { ilg.Else(); } MethodInfo XmlSerializationWriter_CreateUnknownTypeException = typeof(XmlSerializationWriter).GetMethod( "CreateUnknownTypeException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(Object) }); ilg.Ldarg(0); source.Load(typeof(object)); ilg.Call(XmlSerializationWriter_CreateUnknownTypeException); ilg.Throw(); ilg.EndIf(); } // See ilg.If() cond above if (doEndIf) // if (isNullable && choice == null) ilg.EndIf(); } }
private void WriteText(SourceInfo source, TextAccessor text) { if (text.Mapping is PrimitiveMapping) { PrimitiveMapping mapping = (PrimitiveMapping)text.Mapping; Type argType; ilg.Ldarg(0); if (text.Mapping is EnumMapping) { WriteEnumValue((EnumMapping)text.Mapping, source, out argType); } else { WritePrimitiveValue(mapping.TypeDesc, source, out argType); } MethodInfo XmlSerializationWriter_WriteValue = typeof(XmlSerializationWriter).GetMethod( "WriteValue", CodeGenerator.InstanceBindingFlags, new Type[] { argType } ); ilg.Call(XmlSerializationWriter_WriteValue); } else if (text.Mapping is SpecialMapping) { SpecialMapping mapping = (SpecialMapping)text.Mapping; switch (mapping.TypeDesc.Kind) { case TypeKind.Node: MethodInfo WriteTo = source.Type.GetMethod( "WriteTo", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(XmlWriter) } ); MethodInfo XmlSerializationWriter_get_Writer = typeof(XmlSerializationWriter).GetMethod( "get_Writer", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); source.Load(source.Type); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_get_Writer); ilg.Call(WriteTo); break; default: throw new InvalidOperationException(SR.XmlInternalError); } } }
private void WritePrimitiveValue(TypeDesc typeDesc, SourceInfo source, out Type returnType) { if (typeDesc == StringTypeDesc || typeDesc.FormatterName == "String") { source.Load(typeDesc.Type); returnType = typeDesc.Type; } else { if (!typeDesc.HasCustomFormatter) { Type argType = typeDesc.Type; // No ToString(Byte), compiler used ToString(Int16) instead. if (argType == typeof(Byte)) argType = typeof(Int16); // No ToString(UInt16), compiler used ToString(Int32) instead. else if (argType == typeof(UInt16)) argType = typeof(Int32); MethodInfo XmlConvert_ToString = typeof(XmlConvert).GetMethod( "ToString", CodeGenerator.StaticBindingFlags, new Type[] { argType } ); source.Load(typeDesc.Type); ilg.Call(XmlConvert_ToString); returnType = XmlConvert_ToString.ReturnType; } else { // Only these methods below that is non Static and need to ldarg("this") for Call. BindingFlags bindingFlags = CodeGenerator.StaticBindingFlags; if (typeDesc.FormatterName == "XmlQualifiedName") { bindingFlags = CodeGenerator.InstanceBindingFlags; ilg.Ldarg(0); } MethodInfo FromXXX = typeof(XmlSerializationWriter).GetMethod( "From" + typeDesc.FormatterName, bindingFlags, new Type[] { typeDesc.Type } ); source.Load(typeDesc.Type); ilg.Call(FromXXX); returnType = FromXXX.ReturnType; } } }
private void WriteArray(SourceInfo source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc arrayTypeDesc) { if (elements.Length == 0 && text == null) return; string arrayTypeName = arrayTypeDesc.CSharpName; string aName = "a" + arrayTypeDesc.Name; WriteArrayLocalDecl(arrayTypeName, aName, source, arrayTypeDesc); LocalBuilder aLoc = ilg.GetLocal(aName); if (arrayTypeDesc.IsNullable) { ilg.Ldloc(aLoc); ilg.Load(null); ilg.If(Cmp.NotEqualTo); } string cName = null; if (choice != null) { string choiceFullName = choice.Mapping.TypeDesc.CSharpName; SourceInfo choiceSourceInfo = new SourceInfo(choiceSource, null, choice.MemberInfo, null, ilg); cName = "c" + choice.Mapping.TypeDesc.Name; WriteArrayLocalDecl(choiceFullName + "[]", cName, choiceSourceInfo, choice.Mapping.TypeDesc); // write check for the choice identifier array Label labelEnd = ilg.DefineLabel(); Label labelTrue = ilg.DefineLabel(); LocalBuilder cLoc = ilg.GetLocal(cName); ilg.Ldloc(cLoc); ilg.Load(null); ilg.Beq(labelTrue); ilg.Ldloc(cLoc); ilg.Ldlen(); ilg.Ldloc(aLoc); ilg.Ldlen(); ilg.Clt(); ilg.Br(labelEnd); ilg.MarkLabel(labelTrue); ilg.Ldc(true); ilg.MarkLabel(labelEnd); ilg.If(); MethodInfo XmlSerializationWriter_CreateInvalidChoiceIdentifierValueException = typeof(XmlSerializationWriter).GetMethod( "CreateInvalidChoiceIdentifierValueException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldstr(GetCSharpString(choice.Mapping.TypeDesc.FullName)); ilg.Ldstr(GetCSharpString(choice.MemberName)); ilg.Call(XmlSerializationWriter_CreateInvalidChoiceIdentifierValueException); ilg.Throw(); ilg.EndIf(); } WriteArrayItems(elements, text, choice, arrayTypeDesc, aName, cName); if (arrayTypeDesc.IsNullable) { ilg.EndIf(); } }
private void WriteMember(SourceInfo source, string choiceSource, ElementAccessor[] elements, TextAccessor text, ChoiceIdentifierAccessor choice, TypeDesc memberTypeDesc, bool writeAccessors) { if (memberTypeDesc.IsArrayLike && !(elements.Length == 1 && elements[0].Mapping is ArrayMapping)) WriteArray(source, choiceSource, elements, text, choice, memberTypeDesc); else // NOTE: Use different variable name to work around reuse same variable name in different scope WriteElements(source, choiceSource, elements, text, choice, "a" + memberTypeDesc.Name, writeAccessors, memberTypeDesc.IsNullable); }
internal void WriteArrayLocalDecl(string typeName, string variableName, SourceInfo initValue, TypeDesc arrayTypeDesc) { Debug.Assert(typeName == arrayTypeDesc.CSharpName || typeName == arrayTypeDesc.CSharpName + "[]"); Type localType = (typeName == arrayTypeDesc.CSharpName) ? arrayTypeDesc.Type : arrayTypeDesc.Type.MakeArrayType(); // This may need reused varialble to get code compat? LocalBuilder local = initValue.ILG.DeclareOrGetLocal(localType, variableName); if (initValue != null) { initValue.Load(local.LocalType); initValue.ILG.Stloc(local); } }
private void WriteElementCall(string func, Type cast, SourceInfo source, string name, string ns, bool isNullable, bool isAny) { MethodInfo XmlSerializationWriter_func = typeof(XmlSerializationWriter).GetMethod( func, CodeGenerator.InstanceBindingFlags, new Type[] { cast, typeof(String), typeof(String), typeof(Boolean), typeof(Boolean) } ); ilg.Ldarg(0); source.Load(cast); ilg.Ldstr(GetCSharpString(name)); ilg.Ldstr(GetCSharpString(ns)); ilg.Ldc(isNullable); ilg.Ldc(isAny); ilg.Call(XmlSerializationWriter_func); }
private string GenerateMembersElement(XmlMembersMapping xmlMembersMapping) { ElementAccessor element = xmlMembersMapping.Accessor; MembersMapping mapping = (MembersMapping)element.Mapping; bool hasWrapperElement = mapping.HasWrapperElement; bool writeAccessors = mapping.WriteAccessors; string methodName = NextMethodName(element.Name); ilg = new CodeGenerator(this.typeBuilder); ilg.BeginMethod( typeof(void), methodName, new Type[] { typeof(object[]) }, new string[] { "p" }, CodeGenerator.PublicMethodAttributes ); MethodInfo XmlSerializationWriter_WriteStartDocument = typeof(XmlSerializationWriter).GetMethod( "WriteStartDocument", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_WriteStartDocument); MethodInfo XmlSerializationWriter_TopLevelElement = typeof(XmlSerializationWriter).GetMethod( "TopLevelElement", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_TopLevelElement); // in the top-level method add check for the parameters length, // because visual basic does not have a concept of an <out> parameter it uses <ByRef> instead // so sometime we think that we have more parameters then supplied LocalBuilder pLengthLoc = ilg.DeclareLocal(typeof(int), "pLength"); ilg.Ldarg("p"); ilg.Ldlen(); ilg.Stloc(pLengthLoc); if (hasWrapperElement) { WriteStartElement(element.Name, (element.Form == XmlSchemaForm.Qualified ? element.Namespace : ""), false); int xmlnsMember = FindXmlnsIndex(mapping.Members); if (xmlnsMember >= 0) { MemberMapping member = mapping.Members[xmlnsMember]; string source = "((" + typeof(XmlSerializerNamespaces).FullName + ")p[" + xmlnsMember.ToString(CultureInfo.InvariantCulture) + "])"; ilg.Ldloc(pLengthLoc); ilg.Ldc(xmlnsMember); ilg.If(Cmp.GreaterThan); WriteNamespaces(source); ilg.EndIf(); } for (int i = 0; i < mapping.Members.Length; i++) { MemberMapping member = mapping.Members[i]; if (member.Attribute != null && !member.Ignore) { SourceInfo source = new SourceInfo("p[" + i.ToString(CultureInfo.InvariantCulture) + "]", null, null, pLengthLoc.LocalType.GetElementType(), ilg); SourceInfo specifiedSource = null; int specifiedPosition = 0; if (member.CheckSpecified != SpecifiedAccessor.None) { string memberNameSpecified = member.Name + "Specified"; for (int j = 0; j < mapping.Members.Length; j++) { if (mapping.Members[j].Name == memberNameSpecified) { specifiedSource = new SourceInfo("((bool)p[" + j.ToString(CultureInfo.InvariantCulture) + "])", null, null, typeof(bool), ilg); specifiedPosition = j; break; } } } ilg.Ldloc(pLengthLoc); ilg.Ldc(i); ilg.If(Cmp.GreaterThan); if (specifiedSource != null) { Label labelTrue = ilg.DefineLabel(); Label labelEnd = ilg.DefineLabel(); ilg.Ldloc(pLengthLoc); ilg.Ldc(specifiedPosition); ilg.Ble(labelTrue); specifiedSource.Load(typeof(bool)); ilg.Br_S(labelEnd); ilg.MarkLabel(labelTrue); ilg.Ldc(true); ilg.MarkLabel(labelEnd); ilg.If(); } WriteMember(source, member.Attribute, member.TypeDesc, "p"); if (specifiedSource != null) { ilg.EndIf(); } ilg.EndIf(); } } } for (int i = 0; i < mapping.Members.Length; i++) { MemberMapping member = mapping.Members[i]; if (member.Xmlns != null) continue; if (member.Ignore) continue; SourceInfo specifiedSource = null; int specifiedPosition = 0; if (member.CheckSpecified != SpecifiedAccessor.None) { string memberNameSpecified = member.Name + "Specified"; for (int j = 0; j < mapping.Members.Length; j++) { if (mapping.Members[j].Name == memberNameSpecified) { specifiedSource = new SourceInfo("((bool)p[" + j.ToString(CultureInfo.InvariantCulture) + "])", null, null, typeof(bool), ilg); specifiedPosition = j; break; } } } ilg.Ldloc(pLengthLoc); ilg.Ldc(i); ilg.If(Cmp.GreaterThan); if (specifiedSource != null) { Label labelTrue = ilg.DefineLabel(); Label labelEnd = ilg.DefineLabel(); ilg.Ldloc(pLengthLoc); ilg.Ldc(specifiedPosition); ilg.Ble(labelTrue); specifiedSource.Load(typeof(bool)); ilg.Br_S(labelEnd); ilg.MarkLabel(labelTrue); ilg.Ldc(true); ilg.MarkLabel(labelEnd); ilg.If(); } string source = "p[" + i.ToString(CultureInfo.InvariantCulture) + "]"; string enumSource = null; if (member.ChoiceIdentifier != null) { for (int j = 0; j < mapping.Members.Length; j++) { if (mapping.Members[j].Name == member.ChoiceIdentifier.MemberName) { enumSource = "((" + mapping.Members[j].TypeDesc.CSharpName + ")p[" + j.ToString(CultureInfo.InvariantCulture) + "]" + ")"; break; } } #if DEBUG // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe if (enumSource == null) throw new InvalidOperationException(SR.Format(SR.XmlInternalErrorDetails, "Can not find " + member.ChoiceIdentifier.MemberName + " in the members mapping.")); #endif } // override writeAccessors choice when we've written a wrapper element WriteMember(new SourceInfo(source, source, null, null, ilg), enumSource, member.ElementsSortedByDerivation, member.Text, member.ChoiceIdentifier, member.TypeDesc, writeAccessors || hasWrapperElement); if (specifiedSource != null) { ilg.EndIf(); } ilg.EndIf(); } if (hasWrapperElement) { WriteEndElement(); } ilg.EndMethod(); return methodName; }
private void WriteMember(SourceInfo source, AttributeAccessor attribute, TypeDesc memberTypeDesc, string parent) { if (memberTypeDesc.IsAbstract) return; if (memberTypeDesc.IsArrayLike) { string aVar = "a" + memberTypeDesc.Name; string aiVar = "ai" + memberTypeDesc.Name; string iVar = "i"; string fullTypeName = memberTypeDesc.CSharpName; WriteArrayLocalDecl(fullTypeName, aVar, source, memberTypeDesc); if (memberTypeDesc.IsNullable) { ilg.Ldloc(memberTypeDesc.Type, aVar); ilg.Load(null); ilg.If(Cmp.NotEqualTo); } if (attribute.IsList) { if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc)) { string ns = attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : String.Empty; MethodInfo XmlSerializationWriter_get_Writer = typeof(XmlSerializationWriter).GetMethod( "get_Writer", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); MethodInfo XmlWriter_WriteStartAttribute = typeof(XmlWriter).GetMethod( "WriteStartAttribute", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_get_Writer); ilg.Load(null); ilg.Ldstr(GetCSharpString(attribute.Name)); ilg.Ldstr(GetCSharpString(ns)); ilg.Call(XmlWriter_WriteStartAttribute); } else { LocalBuilder sbLoc = ilg.DeclareOrGetLocal(typeof(StringBuilder), "sb"); ConstructorInfo StringBuilder_ctor = typeof(StringBuilder).GetConstructor( CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.New(StringBuilder_ctor); ilg.Stloc(sbLoc); } } TypeDesc arrayElementTypeDesc = memberTypeDesc.ArrayElementTypeDesc; if (memberTypeDesc.IsEnumerable) { throw Globals.NotSupported("CDF15337, DDB176069: Also fail in whidbey IEnumerable member with XmlAttributeAttribute"); } else { LocalBuilder localI = ilg.DeclareOrGetLocal(typeof(Int32), iVar); ilg.For(localI, 0, ilg.GetLocal(aVar)); WriteLocalDecl(aiVar, RaCodeGen.GetStringForArrayMember(aVar, iVar, memberTypeDesc), arrayElementTypeDesc.Type); } if (attribute.IsList) { string methodName; Type methodType; Type argType = typeof(string); // check to see if we can write values of the attribute sequentially if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc)) { ilg.Ldloc(iVar); ilg.Ldc(0); ilg.If(Cmp.NotEqualTo); MethodInfo XmlSerializationWriter_get_Writer = typeof(XmlSerializationWriter).GetMethod( "get_Writer", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); MethodInfo XmlWriter_WriteString = typeof(XmlWriter).GetMethod( "WriteString", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String) } ); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_get_Writer); ilg.Ldstr(" "); ilg.Call(XmlWriter_WriteString); ilg.EndIf(); ilg.Ldarg(0); methodName = "WriteValue"; methodType = typeof(XmlSerializationWriter); } else { MethodInfo StringBuilder_Append = typeof(StringBuilder).GetMethod( "Append", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(string) } ); ilg.Ldloc(iVar); ilg.Ldc(0); ilg.If(Cmp.NotEqualTo); ilg.Ldloc("sb"); ilg.Ldstr(" "); ilg.Call(StringBuilder_Append); ilg.Pop(); ilg.EndIf(); ilg.Ldloc("sb"); methodName = "Append"; methodType = typeof(StringBuilder); } if (attribute.Mapping is EnumMapping) WriteEnumValue((EnumMapping)attribute.Mapping, new SourceInfo(aiVar, aiVar, null, arrayElementTypeDesc.Type, ilg), out argType); else WritePrimitiveValue(arrayElementTypeDesc, new SourceInfo(aiVar, aiVar, null, arrayElementTypeDesc.Type, ilg), out argType); MethodInfo method = methodType.GetMethod( methodName, CodeGenerator.InstanceBindingFlags, new Type[] { argType } ); ilg.Call(method); if (method.ReturnType != typeof(void)) ilg.Pop(); } else { WriteAttribute(new SourceInfo(aiVar, aiVar, null, null, ilg), attribute, parent); } if (memberTypeDesc.IsEnumerable) throw Globals.NotSupported("CDF15337, DDB176069: Also fail in whidbey IEnumerable member with XmlAttributeAttribute"); else ilg.EndFor(); if (attribute.IsList) { // check to see if we can write values of the attribute sequentially if (CanOptimizeWriteListSequence(memberTypeDesc.ArrayElementTypeDesc)) { MethodInfo XmlSerializationWriter_get_Writer = typeof(XmlSerializationWriter).GetMethod( "get_Writer", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); MethodInfo XmlWriter_WriteEndAttribute = typeof(XmlWriter).GetMethod( "WriteEndAttribute", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldarg(0); ilg.Call(XmlSerializationWriter_get_Writer); ilg.Call(XmlWriter_WriteEndAttribute); } else { MethodInfo StringBuilder_get_Length = typeof(StringBuilder).GetMethod( "get_Length", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldloc("sb"); ilg.Call(StringBuilder_get_Length); ilg.Ldc(0); ilg.If(Cmp.NotEqualTo); List<Type> argTypes = new List<Type>(); ilg.Ldarg(0); ilg.Ldstr(GetCSharpString(attribute.Name)); argTypes.Add(typeof(string)); string ns = attribute.Form == XmlSchemaForm.Qualified ? attribute.Namespace : String.Empty; if (ns != null) { ilg.Ldstr(GetCSharpString(ns)); argTypes.Add(typeof(string)); } MethodInfo Object_ToString = typeof(Object).GetMethod( "ToString", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); ilg.Ldloc("sb"); ilg.Call(Object_ToString); argTypes.Add(typeof(string)); MethodInfo XmlSerializationWriter_WriteAttribute = typeof(XmlSerializationWriter).GetMethod( "WriteAttribute", CodeGenerator.InstanceBindingFlags, argTypes.ToArray() ); ilg.Call(XmlSerializationWriter_WriteAttribute); ilg.EndIf(); } } if (memberTypeDesc.IsNullable) { ilg.EndIf(); } } else { WriteAttribute(source, attribute, parent); } }
internal void ILGenLoad(string source, Type type) { if (source.StartsWith("o.@", StringComparison.Ordinal)) { System.Diagnostics.Debug.Assert(memberInfos.ContainsKey(source.Substring(3))); MemberInfo memInfo = memberInfos[source.Substring(3)]; ilg.LoadMember(ilg.GetVariable("o"), memInfo); if (type != null) { Type memType = (memInfo is FieldInfo) ? ((FieldInfo)memInfo).FieldType : ((PropertyInfo)memInfo).PropertyType; ilg.ConvertValue(memType, type); } } else { SourceInfo info = new SourceInfo(source, null, null, null, ilg); info.Load(type); } }
private void WriteChoiceTypeCheck(SourceInfo source, string fullTypeName, ChoiceIdentifierAccessor choice, string enumName, TypeDesc typeDesc) { Label labelFalse = ilg.DefineLabel(); Label labelEnd = ilg.DefineLabel(); source.Load(typeof(object)); ilg.Load(null); ilg.Beq(labelFalse); WriteInstanceOf(source, typeDesc.Type); // Negative ilg.Ldc(false); ilg.Ceq(); ilg.Br(labelEnd); ilg.MarkLabel(labelFalse); ilg.Ldc(false); ilg.MarkLabel(labelEnd); ilg.If(); MethodInfo XmlSerializationWriter_CreateMismatchChoiceException = typeof(XmlSerializationWriter).GetMethod( "CreateMismatchChoiceException", CodeGenerator.InstanceBindingFlags, new Type[] { typeof(String), typeof(String), typeof(String) } ); ilg.Ldarg(0); ilg.Ldstr(GetCSharpString(typeDesc.FullName)); ilg.Ldstr(GetCSharpString(choice.MemberName)); ilg.Ldstr(GetCSharpString(enumName)); ilg.Call(XmlSerializationWriter_CreateMismatchChoiceException); ilg.Throw(); ilg.EndIf(); }
private void WriteCheckDefault(SourceInfo source, object value, bool isNullable) { if (value is string && ((string)value).Length == 0) { // special case for string compare Label labelEnd = ilg.DefineLabel(); Label labelFalse = ilg.DefineLabel(); Label labelTrue = ilg.DefineLabel(); source.Load(typeof(string)); if (isNullable) // check == null with false ilg.Brfalse(labelTrue); else //check != null with false ilg.Brfalse(labelFalse); MethodInfo String_get_Length = typeof(string).GetMethod( "get_Length", CodeGenerator.InstanceBindingFlags, Array.Empty<Type>() ); source.Load(typeof(string)); ilg.Call(String_get_Length); ilg.Ldc(0); ilg.Cne(); ilg.Br(labelEnd); if (isNullable) { ilg.MarkLabel(labelTrue); ilg.Ldc(true); } else { ilg.MarkLabel(labelFalse); ilg.Ldc(false); } ilg.MarkLabel(labelEnd); ilg.If(); } else { if (value == null) { source.Load(typeof(object)); ilg.Load(null); ilg.Cne(); } else if (value.GetType().GetTypeInfo().IsPrimitive) { source.Load(null); ilg.Ldc(Convert.ChangeType(value, source.Type, CultureInfo.InvariantCulture)); ilg.Cne(); } else { Type valueType = value.GetType(); source.Load(valueType); ilg.Ldc(value is string ? GetCSharpString((string)value) : value); MethodInfo op_Inequality = valueType.GetMethod( "op_Inequality", CodeGenerator.StaticBindingFlags, new Type[] { valueType, valueType } ); if (op_Inequality != null) ilg.Call(op_Inequality); else ilg.Cne(); } ilg.If(); } }
private void WriteEnumValue(EnumMapping mapping, SourceInfo source, out Type returnType) { string methodName = ReferenceMapping(mapping); #if DEBUG // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe if (methodName == null) throw new InvalidOperationException(SR.Format(SR.XmlInternalErrorMethod, mapping.TypeDesc.Name)); #endif // For enum, its write method (eg. Write1_Gender) could be called multiple times // prior to its declaration. MethodBuilder methodBuilder = EnsureMethodBuilder(typeBuilder, methodName, CodeGenerator.PrivateMethodAttributes, typeof(string), new Type[] { mapping.TypeDesc.Type }); ilg.Ldarg(0); source.Load(mapping.TypeDesc.Type); ilg.Call(methodBuilder); returnType = typeof(string); }