private void WriteElement(string 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)
{
Writer.Write("if (");
Writer.Write(source);
Writer.WriteLine(" != null) {");
Writer.Indent++;
string fullTypeName = element.Mapping.TypeDesc.BaseTypeDesc.CSharpName;
string castedSource = source;
if (!element.Mapping.TypeDesc.BaseTypeDesc.UseReflection)
castedSource = "((" + fullTypeName + ")" + source + ")";
ElementAccessor e = element.Clone();
e.Mapping = ((NullableMapping)element.Mapping).BaseMapping;
WriteElement(e.Any ? source : castedSource, e, arrayName, writeAccessor);
Writer.Indent--;
Writer.WriteLine("}");
if (element.IsNullable)
{
Writer.WriteLine("else {");
Writer.Indent++;
WriteLiteralNullTag(element.Name, element.Form == XmlSchemaForm.Qualified ? element.Namespace : "");
Writer.Indent--;
Writer.WriteLine("}");
}
}
else if (element.Mapping is ArrayMapping)
{
ArrayMapping mapping = (ArrayMapping)element.Mapping;
if (mapping.IsSoap)
{
Writer.Write("WritePotentiallyReferencingElement(");
WriteQuotedCSharpString(name);
Writer.Write(", ");
WriteQuotedCSharpString(ns);
Writer.Write(", ");
Writer.Write(source);
if (!writeAccessor)
{
Writer.Write(", ");
Writer.Write(RaCodeGen.GetStringForTypeof(mapping.TypeDesc.CSharpName, mapping.TypeDesc.UseReflection));
Writer.Write(", true, ");
}
else
{
Writer.Write(", null, false, ");
}
WriteValue(element.IsNullable);
Writer.WriteLine(");");
}
else if (element.IsUnbounded)
{
TypeDesc td = mapping.TypeDesc.CreateArrayTypeDesc();
string fullTypeName = td.CSharpName;
string elementArrayName = "el" + arrayName;
string arrayIndex = "c" + elementArrayName;
Writer.WriteLine("{");
Writer.Indent++;
WriteArrayLocalDecl(fullTypeName, elementArrayName, source, mapping.TypeDesc);
if (element.IsNullable)
{
WriteNullCheckBegin(elementArrayName, element);
}
else
{
if (mapping.TypeDesc.IsNullable)
{
Writer.Write("if (");
Writer.Write(elementArrayName);
Writer.Write(" != null)");
}
Writer.WriteLine("{");
Writer.Indent++;
}
Writer.Write("for (int ");
Writer.Write(arrayIndex);
Writer.Write(" = 0; ");
Writer.Write(arrayIndex);
Writer.Write(" < ");
if (td.IsArray)
{
Writer.Write(elementArrayName);
Writer.Write(".Length");
}
else
{
Writer.Write("((");
Writer.Write(typeof(ICollection).FullName);
Writer.Write(")");
Writer.Write(elementArrayName);
Writer.Write(").Count");
}
Writer.Write("; ");
Writer.Write(arrayIndex);
Writer.WriteLine("++) {");
Writer.Indent++;
element.IsUnbounded = false;
WriteElement(elementArrayName + "[" + arrayIndex + "]", element, arrayName, writeAccessor);
element.IsUnbounded = true;
Writer.Indent--;
Writer.WriteLine("}");
Writer.Indent--;
Writer.WriteLine("}");
Writer.Indent--;
Writer.WriteLine("}");
}
else
{
string fullTypeName = mapping.TypeDesc.CSharpName;
Writer.WriteLine("{");
Writer.Indent++;
WriteArrayLocalDecl(fullTypeName, arrayName, source, mapping.TypeDesc);
if (element.IsNullable)
{
WriteNullCheckBegin(arrayName, element);
}
else
{
if (mapping.TypeDesc.IsNullable)
{
Writer.Write("if (");
Writer.Write(arrayName);
Writer.Write(" != null)");
}
Writer.WriteLine("{");
Writer.Indent++;
}
WriteStartElement(name, ns, false);
WriteArrayItems(mapping.ElementsSortedByDerivation, null, null, mapping.TypeDesc, arrayName, null);
WriteEndElement();
Writer.Indent--;
Writer.WriteLine("}");
Writer.Indent--;
Writer.WriteLine("}");
}
}
else if (element.Mapping is EnumMapping)
{
if (element.Mapping.IsSoap)
{
string methodName = (string)MethodNames[element.Mapping];
Writer.Write("Writer.WriteStartElement(");
WriteQuotedCSharpString(name);
Writer.Write(", ");
WriteQuotedCSharpString(ns);
Writer.WriteLine(");");
Writer.Write(methodName);
Writer.Write("(");
Writer.Write(source);
Writer.WriteLine(");");
WriteEndElement();
}
else
{
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.IsSoap, mapping);
else
{
string suffixNullable = mapping.IsSoap ? "Encoded" : "Literal";
string suffixRaw = mapping.TypeDesc.XmlEncodingNotRequired ? "Raw" : "";
WritePrimitive(element.IsNullable ? ("WriteNullableString" + suffixNullable + suffixRaw) : ("WriteElementString" + suffixRaw),
name, ns, element.Default, source, mapping, mapping.IsSoap, true, element.IsNullable);
}
}
else if (element.Mapping is StructMapping)
{
StructMapping mapping = (StructMapping)element.Mapping;
if (mapping.IsSoap)
{
Writer.Write("WritePotentiallyReferencingElement(");
WriteQuotedCSharpString(name);
Writer.Write(", ");
WriteQuotedCSharpString(ns);
Writer.Write(", ");
Writer.Write(source);
if (!writeAccessor)
{
Writer.Write(", ");
Writer.Write(RaCodeGen.GetStringForTypeof(mapping.TypeDesc.CSharpName, mapping.TypeDesc.UseReflection));
Writer.Write(", true, ");
}
else
{
Writer.Write(", null, false, ");
}
WriteValue(element.IsNullable);
}
else
{
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) + Environment.StackTrace);
#endif
Writer.Write(methodName);
Writer.Write("(");
WriteQuotedCSharpString(name);
Writer.Write(", ");
if (ns == null)
Writer.Write("null");
else
{
WriteQuotedCSharpString(ns);
}
Writer.Write(", ");
Writer.Write(source);
if (mapping.TypeDesc.IsNullable)
{
Writer.Write(", ");
WriteValue(element.IsNullable);
}
Writer.Write(", false");
}
Writer.WriteLine(");");
}
else if (element.Mapping is SpecialMapping)
{
SpecialMapping mapping = (SpecialMapping)element.Mapping;
bool useReflection = mapping.TypeDesc.UseReflection;
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
Writer.Write("if ((");
Writer.Write(source);
Writer.Write(") is ");
Writer.Write(typeof(XmlNode).FullName);
Writer.Write(" || ");
Writer.Write(source);
Writer.Write(" == null");
Writer.WriteLine(") {");
Writer.Indent++;
WriteElementCall("WriteElementLiteral", typeof(XmlNode), source, name, ns, element.IsNullable, element.Any);
Writer.Indent--;
Writer.WriteLine("}");
Writer.WriteLine("else {");
Writer.Indent++;
Writer.Write("throw CreateInvalidAnyTypeException(");
Writer.Write(source);
Writer.WriteLine(");");
Writer.Indent--;
Writer.WriteLine("}");
}
}
else
{
throw new InvalidOperationException(SR.XmlInternalError);
}
}