/// <summary> /// Append the definition of the SetState method required to fulfil the IMobileObject interface /// </summary> /// <param name="textWriter">The IndentedTextWriter instance to which to append the method definition</param> /// <param name="typeDefinition">The definition of the type for which we are generating</param> private void AppendSetStateMethod(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition) { textWriter.WriteLine("void IMobileObject.SetState(SerializationInfo info)"); AppendBlockStart(textWriter); foreach (ExtractedFieldDefinition fieldDefinition in typeDefinition.Fields) { if (IsChildToExpose(fieldDefinition)) { continue; } AppendSetMemberStateMethod(textWriter, fieldDefinition); } foreach (ExtractedPropertyDefinition propertyDefinition in typeDefinition.Properties) { if (IsChildToExpose(propertyDefinition)) { continue; } AppendSetMemberStateMethod(textWriter, propertyDefinition); } AppendBlockEnd(textWriter); textWriter.WriteLine(); }
/// <summary> /// Append the definition of the SetChildren method required to fulfil the IMobileObject interface /// </summary> /// <param name="textWriter">The IndentedTextWriter instance to which to append the method definition</param> /// <param name="typeDefinition">The definition of the type for which we are generating</param> private void AppendSetChildrenMethod(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition) { textWriter.WriteLine("void IMobileObject.SetChildren(SerializationInfo info, MobileFormatter formatter)"); AppendBlockStart(textWriter); if (HasChildrenToExpose(typeDefinition)) { textWriter.WriteLine("SerializationInfo.ChildData childData;"); textWriter.WriteLine(); } foreach (ExtractedFieldDefinition fieldDefinition in typeDefinition.Fields) { if (!IsChildToExpose(fieldDefinition)) { continue; } AppendDeserializeChildFragment(textWriter, fieldDefinition); } foreach (ExtractedPropertyDefinition propertyDefinition in typeDefinition.Properties) { if (!IsChildToExpose(propertyDefinition)) { continue; } AppendDeserializeChildFragment(textWriter, propertyDefinition); } AppendBlockEnd(textWriter); textWriter.WriteLine(); }
/// <summary> /// Build the text of a partial type that implements the IMobileObject /// interface so that the target type automatically offers mobile serialization /// </summary> /// <param name="typeDefinition">The definition of the type for which serialization is required</param> /// <returns>Generated code to fulfil the required serialization</returns> internal GenerationResults BuildPartialTypeDefinition(ExtractedTypeDefinition typeDefinition) { GenerationResults generationResults; IndentedTextWriter textWriter; using (StringWriter stringWriter = new StringWriter()) { textWriter = new IndentedTextWriter(stringWriter, "\t"); AppendUsingStatements(textWriter, typeDefinition); AppendContainerDefinitions(textWriter, typeDefinition); AppendTypeDefinition(textWriter, typeDefinition); AppendBlockStart(textWriter); AppendGetChildrenMethod(textWriter, typeDefinition); AppendGetStateMethod(textWriter, typeDefinition); AppendSetChildrenMethod(textWriter, typeDefinition); AppendSetStateMethod(textWriter, typeDefinition); AppendBlockEnd(textWriter); AppendContainerDefinitionClosures(textWriter, typeDefinition); generationResults = new GenerationResults() { FullyQualifiedName = typeDefinition.FullyQualifiedName, GeneratedSource = stringWriter.ToString() }; } return(generationResults); }
/// <summary> /// Append the definitions of the containers in which the partial type is to reside /// </summary> /// <param name="textWriter">The IndentedTextWriter instance to which to append the definitions</param> /// <param name="typeDefinition">The definition of the type for which we are generating</param> private void AppendContainerDefinitions(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition) { foreach (ExtractedContainerDefinition containerDefinition in typeDefinition.ContainerDefinitions) { textWriter.WriteLine(containerDefinition.FullDefinition); AppendBlockStart(textWriter); } }
/// <summary> /// Append the type definition of the partial we are generating /// </summary> /// <param name="textWriter">The IndentedTextWriter instance to which to append the type definition</param> /// <param name="typeDefinition">The definition of the type for which we are generating</param> private void AppendTypeDefinition(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition) { textWriter.WriteLine("[Serializable]"); textWriter.Write(typeDefinition.Scope); textWriter.Write(" partial "); textWriter.Write(typeDefinition.TypeKind); textWriter.Write(" "); textWriter.Write(typeDefinition.TypeName); textWriter.Write(" : IMobileObject"); textWriter.WriteLine(); }
/// <summary> /// Generate a partial type to complete a type that has been identified as a target /// </summary> /// <param name="context">The execution context of generation</param> /// <param name="typeDeclaration">The declaration of the type for which to generate code</param> public void GeneratePartialType(GeneratorExecutionContext context, ExtractedTypeDefinition typeDefinition) { GenerationResults generationResults; SerializationPartialBuilder builder = new SerializationPartialBuilder(); // Build the text for the generated type using the builder generationResults = builder.BuildPartialTypeDefinition(typeDefinition); // Add the generated source to the output context.AddSource($"{generationResults.FullyQualifiedName}.g", SourceText.From(generationResults.GeneratedSource, Encoding.UTF8)); }
/// <summary> /// Append the required using statements required on a partial class in /// order for it to compile the code we have generated /// </summary> /// <param name="textWriter">The IndentedTextWriter instance to which to append the usings</param> /// <param name="typeDefinition">The definition of the type for which we are generating</param> private void AppendUsingStatements(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition) { HashSet <string> requiredNamespaces; requiredNamespaces = GetRequiredNamespaces(typeDefinition); foreach (string requiredNamespace in requiredNamespaces) { textWriter.Write("using "); textWriter.Write(requiredNamespace); textWriter.WriteLine(";"); } textWriter.WriteLine(); }
/// <summary> /// Retrieve all of the namespaces that are required for generation of the defined type /// </summary> /// <param name="typeDefinition">The definition of the type for which generation is being performed</param> /// <returns>A hashset of all of the namespaces required for generation</returns> private HashSet <string> GetRequiredNamespaces(ExtractedTypeDefinition typeDefinition) { HashSet <string> requiredNamespaces = new HashSet <string>() { "System", "Csla.Serialization.Mobile" }; foreach (ExtractedFieldDefinition fieldDefinition in typeDefinition.Fields) { requiredNamespaces.Add(fieldDefinition.TypeDefinition.TypeNamespace); } foreach (ExtractedPropertyDefinition propertyDefinition in typeDefinition.Properties) { requiredNamespaces.Add(propertyDefinition.TypeDefinition.TypeNamespace); } requiredNamespaces.Remove(typeDefinition.Namespace); return(requiredNamespaces); }
/// <summary> /// Determine if a type definition exposes any members that must be treated as children /// </summary> /// <param name="typeDefinition">The type definition to be checked for children</param> /// <returns>Boolean true of the definition exposes any members that have to be treated as children</returns> private bool HasChildrenToExpose(ExtractedTypeDefinition typeDefinition) { return(typeDefinition.Properties.Any(p => IsChildToExpose(p)) || typeDefinition.Fields.Any(f => IsChildToExpose(f))); }
/// <summary> /// Append the definitions of the containers in which the partial type is to reside /// </summary> /// <param name="textWriter">The IndentedTextWriter instance to which to append the definitions</param> /// <param name="typeDefinition">The definition of the type for which we are generating</param> private void AppendContainerDefinitionClosures(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition) { foreach (ExtractedContainerDefinition containerDefinition in typeDefinition.ContainerDefinitions) { AppendBlockEnd(textWriter); } }