CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
SerializationPartialBuilder.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="SerializationPartialBuilder.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>Builds the text of a partial type to implement the IMobileObject interface</summary>
7//-----------------------------------------------------------------------
8using Microsoft.CodeAnalysis;
9using Microsoft.CodeAnalysis.CSharp.Syntax;
10using System;
11using System.CodeDom.Compiler;
12using System.Collections.Generic;
13using System.IO;
14using System.Linq;
15using System.Text;
16
18{
19
24 internal class SerializationPartialBuilder
25 {
26
33 internal GenerationResults BuildPartialTypeDefinition(ExtractedTypeDefinition typeDefinition)
34 {
35 GenerationResults generationResults;
36 IndentedTextWriter textWriter;
37
38 using (StringWriter stringWriter = new StringWriter())
39 {
40 textWriter = new IndentedTextWriter(stringWriter, "\t");
41
42 AppendUsingStatements(textWriter, typeDefinition);
43 AppendContainerDefinitions(textWriter, typeDefinition);
44
45 AppendTypeDefinition(textWriter, typeDefinition);
46 AppendBlockStart(textWriter);
47
48 AppendGetChildrenMethod(textWriter, typeDefinition);
49 AppendGetStateMethod(textWriter, typeDefinition);
50 AppendSetChildrenMethod(textWriter, typeDefinition);
51 AppendSetStateMethod(textWriter, typeDefinition);
52
53 AppendBlockEnd(textWriter);
54
55 AppendContainerDefinitionClosures(textWriter, typeDefinition);
56
57 generationResults = new GenerationResults()
58 {
59 FullyQualifiedName = typeDefinition.FullyQualifiedName,
60 GeneratedSource = stringWriter.ToString()
61 };
62 }
63
64 return generationResults;
65 }
66
67 #region Private Helper Methods
68
73 private void AppendBlockStart(IndentedTextWriter textWriter)
74 {
75 textWriter.WriteLine("{");
76 textWriter.Indent++;
77 }
78
83 private void AppendBlockEnd(IndentedTextWriter textWriter)
84 {
85 textWriter.Indent--;
86 textWriter.WriteLine("}");
87 }
88
95 private void AppendUsingStatements(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition)
96 {
97 HashSet<string> requiredNamespaces;
98
99 requiredNamespaces = GetRequiredNamespaces(typeDefinition);
100
101 foreach (string requiredNamespace in requiredNamespaces)
102 {
103 textWriter.Write("using ");
104 textWriter.Write(requiredNamespace);
105 textWriter.WriteLine(";");
106 }
107
108 textWriter.WriteLine();
109 }
110
116 private HashSet<string> GetRequiredNamespaces(ExtractedTypeDefinition typeDefinition)
117 {
118 HashSet<string> requiredNamespaces = new HashSet<string>() { "System", "Csla.Serialization.Mobile" };
119
120 foreach (ExtractedFieldDefinition fieldDefinition in typeDefinition.Fields)
121 {
122 requiredNamespaces.Add(fieldDefinition.TypeDefinition.TypeNamespace);
123 }
124
125 foreach (ExtractedPropertyDefinition propertyDefinition in typeDefinition.Properties)
126 {
127 requiredNamespaces.Add(propertyDefinition.TypeDefinition.TypeNamespace);
128 }
129
130 requiredNamespaces.Remove(typeDefinition.Namespace);
131
132 return requiredNamespaces;
133 }
134
140 private void AppendContainerDefinitions(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition)
141 {
142 foreach (ExtractedContainerDefinition containerDefinition in typeDefinition.ContainerDefinitions)
143 {
144 textWriter.WriteLine(containerDefinition.FullDefinition);
145 AppendBlockStart(textWriter);
146 }
147 }
148
154 private void AppendContainerDefinitionClosures(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition)
155 {
156 foreach (ExtractedContainerDefinition containerDefinition in typeDefinition.ContainerDefinitions)
157 {
158 AppendBlockEnd(textWriter);
159 }
160 }
161
167 private void AppendTypeDefinition(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition)
168 {
169 textWriter.WriteLine("[Serializable]");
170 textWriter.Write(typeDefinition.Scope);
171 textWriter.Write(" partial ");
172 textWriter.Write(typeDefinition.TypeKind);
173 textWriter.Write(" ");
174 textWriter.Write(typeDefinition.TypeName);
175 textWriter.Write(" : IMobileObject");
176 textWriter.WriteLine();
177 }
178
184 private void AppendGetChildrenMethod(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition)
185 {
186 textWriter.WriteLine("void IMobileObject.GetChildren(SerializationInfo info, MobileFormatter formatter)");
187 AppendBlockStart(textWriter);
188 if (HasChildrenToExpose(typeDefinition))
189 {
190 textWriter.WriteLine("IMobileObject mobileObject;");
191 textWriter.WriteLine("SerializationInfo childInfo;");
192 textWriter.WriteLine();
193 }
194
195 foreach (ExtractedFieldDefinition fieldDefinition in typeDefinition.Fields)
196 {
197 if (!IsChildToExpose(fieldDefinition)) continue;
198
199 AppendSerializeChildFragment(textWriter, fieldDefinition);
200 }
201
202 foreach (ExtractedPropertyDefinition propertyDefinition in typeDefinition.Properties)
203 {
204 if (!IsChildToExpose(propertyDefinition)) continue;
205
206 AppendSerializeChildFragment(textWriter, propertyDefinition);
207 }
208
209 AppendBlockEnd(textWriter);
210 textWriter.WriteLine();
211 }
212
218 private void AppendSerializeChildFragment(IndentedTextWriter textWriter, IMemberDefinition memberDefinition)
219 {
220 textWriter.Write("mobileObject = ");
221 textWriter.Write(memberDefinition.MemberName);
222 textWriter.WriteLine(" as IMobileObject;");
223 textWriter.WriteLine("childInfo = formatter.SerializeObject(mobileObject);");
224 textWriter.Write("info.AddChild(nameof(");
225 textWriter.Write(memberDefinition.MemberName);
226 textWriter.WriteLine("), childInfo.ReferenceId, true);");
227 }
228
234 private void AppendSetChildrenMethod(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition)
235 {
236 textWriter.WriteLine("void IMobileObject.SetChildren(SerializationInfo info, MobileFormatter formatter)");
237 AppendBlockStart(textWriter);
238
239 if (HasChildrenToExpose(typeDefinition))
240 {
241 textWriter.WriteLine("SerializationInfo.ChildData childData;");
242 textWriter.WriteLine();
243 }
244
245 foreach (ExtractedFieldDefinition fieldDefinition in typeDefinition.Fields)
246 {
247 if (!IsChildToExpose(fieldDefinition)) continue;
248
249 AppendDeserializeChildFragment(textWriter, fieldDefinition);
250 }
251
252 foreach (ExtractedPropertyDefinition propertyDefinition in typeDefinition.Properties)
253 {
254 if (!IsChildToExpose(propertyDefinition)) continue;
255
256 AppendDeserializeChildFragment(textWriter, propertyDefinition);
257 }
258
259 AppendBlockEnd(textWriter);
260 textWriter.WriteLine();
261 }
262
268 private void AppendDeserializeChildFragment(IndentedTextWriter textWriter, IMemberDefinition memberDefinition)
269 {
270 textWriter.Write("if (info.Children.ContainsKey(nameof(");
271 textWriter.Write(memberDefinition.MemberName);
272 textWriter.WriteLine(")))");
273 AppendBlockStart(textWriter);
274
275 textWriter.Write("childData = info.Children[nameof(");
276 textWriter.Write(memberDefinition.MemberName);
277 textWriter.WriteLine(")];");
278 textWriter.WriteLine();
279 textWriter.Write(memberDefinition.MemberName);
280 textWriter.Write(" = formatter.GetObject(childData.ReferenceId) as ");
281 textWriter.Write(memberDefinition.TypeDefinition.TypeName);
282 textWriter.WriteLine(";");
283
284 AppendBlockEnd(textWriter);
285 }
286
292 private void AppendGetStateMethod(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition)
293 {
294 textWriter.WriteLine("void IMobileObject.GetState(SerializationInfo info)");
295 AppendBlockStart(textWriter);
296
297 foreach (ExtractedFieldDefinition fieldDefinition in typeDefinition.Fields)
298 {
299 if (IsChildToExpose(fieldDefinition)) continue;
300
301 AppendGetMemberStateFragment(textWriter, fieldDefinition);
302 }
303
304 foreach (ExtractedPropertyDefinition propertyDefinition in typeDefinition.Properties)
305 {
306 if (IsChildToExpose(propertyDefinition)) continue;
307
308 AppendGetMemberStateFragment(textWriter, propertyDefinition);
309 }
310
311 AppendBlockEnd(textWriter);
312 textWriter.WriteLine();
313 }
314
320 private void AppendGetMemberStateFragment(IndentedTextWriter textWriter, IMemberDefinition memberDefinition)
321 {
322 textWriter.Write("info.AddValue(nameof(");
323 textWriter.Write(memberDefinition.MemberName);
324 textWriter.Write("), ");
325 textWriter.Write(memberDefinition.MemberName);
326 textWriter.WriteLine(");");
327 }
328
334 private void AppendSetStateMethod(IndentedTextWriter textWriter, ExtractedTypeDefinition typeDefinition)
335 {
336 textWriter.WriteLine("void IMobileObject.SetState(SerializationInfo info)");
337 AppendBlockStart(textWriter);
338
339 foreach (ExtractedFieldDefinition fieldDefinition in typeDefinition.Fields)
340 {
341 if (IsChildToExpose(fieldDefinition)) continue;
342
343 AppendSetMemberStateMethod(textWriter, fieldDefinition);
344 }
345
346 foreach (ExtractedPropertyDefinition propertyDefinition in typeDefinition.Properties)
347 {
348 if (IsChildToExpose(propertyDefinition)) continue;
349
350 AppendSetMemberStateMethod(textWriter, propertyDefinition);
351 }
352
353 AppendBlockEnd(textWriter);
354 textWriter.WriteLine();
355 }
356
362 private void AppendSetMemberStateMethod(IndentedTextWriter textWriter, IMemberDefinition memberDefinition)
363 {
364 textWriter.Write(memberDefinition.MemberName);
365 textWriter.Write(" = info.GetValue<");
366 textWriter.Write(memberDefinition.TypeDefinition.TypeName);
367 textWriter.Write(">(nameof(");
368 textWriter.Write(memberDefinition.MemberName);
369 textWriter.WriteLine("));");
370 }
371
377 private bool HasChildrenToExpose(ExtractedTypeDefinition typeDefinition)
378 {
379 return typeDefinition.Properties.Any(p => IsChildToExpose(p)) ||
380 typeDefinition.Fields.Any(f => IsChildToExpose(f));
381 }
382
388 private bool IsChildToExpose(IMemberDefinition memberDefinition)
389 {
390 return memberDefinition.TypeDefinition.IsAutoSerializable || memberDefinition.TypeDefinition.ImplementsIMobileObject;
391 }
392
393 #endregion
394
395 }
396
397}