internal Class CreateSerializerFor(TypeNode type) { // todo: look in the genCache for other serializer assemblies that may have already // created the serializer for this type and make an assembly reference to that // serializer instead of creating a complete duplicate. TypeNode saved = tempChecker.currentType; Class c = (Class)serializers[type]; if (c != null) return c; c = new Class(); c.Flags = TypeFlags.Class | TypeFlags.BeforeFieldInit; // copy the accessibility of the type we are serializing. c.Flags |= (type.Flags & (TypeFlags.Public | TypeFlags.NestedAssembly)); c.Name = Identifier.For(GetSerializerName(type)); c.Namespace = Identifier.For(GetSerializerNamespace(type)); c.DeclaringModule = this.module; c.Members = new MemberList(); c.Attributes = new AttributeList(); c.BaseClass = Runtime.XmlSerializer; tempChecker.currentType = c; InstanceInitializer ii = Runtime.XmlSerializerAttribute.GetConstructor(); MemberBinding mb = new MemberBinding(null, ii); mb.Type = Runtime.XmlSerializerAttribute; c.Attributes.Add(new AttributeNode(mb, null)); if (cunit != null) { cunit.Namespaces[0].Types.Add(c); } this.module.Types.Add(c); Identifier typeId = Identifier.For("type"); // what we are writing to. Identifier rootName = Identifier.For("rootName"); // what we are writing to. Identifier rootNamespace = Identifier.For("rootNamespace"); // what we are writing to. // Constructor Method constructor = new InstanceInitializer(); constructor.Name = StandardIds.Ctor; constructor.DeclaringType = c; constructor.Flags = MethodFlags.Public|MethodFlags.HideBySig|MethodFlags.SpecialName|MethodFlags.RTSpecialName; constructor.Parameters = new ParameterList(); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, typeId, SystemTypes.Type, null, null)); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null)); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null)); constructor.ReturnType = SystemTypes.Void; c.Members.Add(constructor); // pass args thru to base XmlSerializer constructor. Block b = constructor.Body = new Block(new StatementList()); b.Statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(new Base(), StandardIds.Ctor), new ExpressionList(typeId, rootName, rootNamespace), NodeType.Call))); //AddConsoleWrite(b.Statements, new Literal("Hello!!",SystemTypes.String)); // Serialize(T source, XmlSerializationWriter writer) method Identifier src = Identifier.For("source"); // object being serialized. Identifier writer = Identifier.For("writer"); // what we are writing to. Method serialize = new Method(); serialize.Name = Identifier.For("Serialize"); serialize.DeclaringType = c; serialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig; serialize.Parameters = new ParameterList(); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, src, type, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, writer, Runtime.XmlSerializationWriter, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null)); serialize.ReturnType = SystemTypes.Void; c.Members.Add(serialize); // T Deserialize(XmlReader reader, bool required, out bool result) method Identifier reader = Identifier.For("reader"); // what we are reading from. Identifier required = Identifier.For("required"); // whether an object is required or not. Identifier result = Identifier.For("result"); // whether we found anything. Method deserialize = new Method(); deserialize.Name = Identifier.For("Deserialize"); deserialize.DeclaringType = c; deserialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig; deserialize.Parameters = new ParameterList(); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, reader, Runtime.XmlSerializationReader, null, null)); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, required, SystemTypes.Boolean, null, null)); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.Out, result, SystemTypes.Boolean.GetReferenceType(), null, null)); deserialize.ReturnType = type; c.Members.Add(deserialize); // It is important that we add the serializer to the cache AFTER we create the methods, but // BEFORE we create the method bodies so that we can handle recurrsive calls to AddCallSerializer which // happens in recurrsive structures like "class Foo { public Foo f; }". Otherwise we'd get stuck in an // infinite loop. serializers[type] = c; // Body of serialize method. b = serialize.Body = new Block(new StatementList()); StatementList statements = b.Statements; if (!AddWriteSimpleType(type, statements, c, writer, src, rootName, rootNamespace)) { MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteStartElement")); call.Operands = new ExpressionList(); call.Operands.Add(rootName); call.Operands.Add(rootNamespace); statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne), new Block(new StatementList(new ExpressionStatement(call))),null)); Expression source = src; if (type.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, c), type); type = Checker.GetCollectionElementType(type); source = CastTo(src, type);//unbox it } if (type is TupleType) { AddWriteTuple(type as TupleType, statements, c, source, writer); } else if (type is TypeUnion) { AddWriteChoice(type as TypeUnion, statements, c, source, writer); } else if (IsStream(type)) { AddWriteStream(type, statements, c, source, writer); } else { SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache); SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler); statements = AddCheckForNull(statements, Duplicate(src, c), type); AddWriteAttributes(statements, c, writer, source, validator); AddWriteContent(type, statements, c, writer, source, validator); } call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteEndElement")); call.Operands = new ExpressionList(); statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne), new Block(new StatementList(new ExpressionStatement(call))),null)); } // body of deserialize method. b = deserialize.Body = new Block(new StatementList()); statements = b.Statements; Local target = new Local(Identifier.Empty, type); if (type.Template == SystemTypes.GenericBoxed){ type = Checker.GetCollectionElementType(type); } if (type is TupleType) { AddReadTuple(b, type as TupleType, statements, reader, target, required, result); } else if (type is TypeUnion) { AddReadChoice(b, type as TypeUnion, statements, reader, target, required, result); } else if (IsStream(type)) { AddReadStream(b, type, statements, reader, target, result); } else { if (type is TypeAlias) { type = ((TypeAlias)type).AliasedType; } // Then we are already positioned on the element to be deserialized. statements.Add(new AssignmentStatement(required, Literal.True)); if (!AddReadSimpleType(type, statements, reader, target, result, false)) { if (!type.IsValueType && !type.IsAbstract && type.GetConstructor() != null) { Construct cons = new Construct(new MemberBinding(null, type), new ExpressionList(), type); statements.Add(new AssignmentStatement(target, cons)); } SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache); SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler); AddReadAttributes(type, statements, reader, target, validator); AddReadContent(c, b, type, statements, reader, target, required, result, validator); } } statements.Add(new Return(target)); tempChecker.currentType = saved; return c; }