private static SyntaxList <StatementSyntax> GenerateStatements <T>(T item) { var context = new CacheBuilderContext(); var variableName = Buildup(item, context); context.Statements.Add(SyntaxFactory.ParseStatement($"return {variableName};")); return(SyntaxFactory.List(context.Statements)); }
private static string Buildup(object target, CacheBuilderContext context) { var type = target.GetType(); if (!context.TypeFieldsCache.TryGetValue(type, out ICollection <FieldInfo> fields)) { fields = GetAllFields(type); context.TypeFieldsCache[type] = fields; } // Create an instance of the type, and generate a variable name for that instance. object obj = FormatterServices.GetUninitializedObject(type); string variableName = CreateVariableName("var", context.ExistingVariables); context.ObjectCache[target] = obj; context.VariableMap[obj] = variableName; context.Statements.Add(SyntaxFactory.ParseStatement($"var {variableName} = CreateObject<{type.FullName}>();")); foreach (var field in fields) { string fieldVariableName = null; // If the field is not public, we have to set it via reflection. Initialize the Type and FieldInfo variables. if (!field.IsPublic) { if (!context.VariableMap.TryGetValue(field.DeclaringType, out string typeVariableName)) { typeVariableName = CreateVariableName("type", context.ExistingVariables); context.VariableMap[type] = typeVariableName; context.Statements.Add(SyntaxFactory.ParseStatement($"var {typeVariableName} = typeof({field.DeclaringType.FullName});")); } if (!context.VariableMap.TryGetValue(field, out fieldVariableName)) { fieldVariableName = CreateVariableName("field", context.ExistingVariables); context.VariableMap[field] = fieldVariableName; context.Statements.Add(SyntaxFactory.ParseStatement($"var {fieldVariableName} = {typeVariableName}.GetField(\"{field.Name}\", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);")); } } var fieldValue = field.GetValue(target); string variableNameOrValue = null; // Generate the syntax for the field value. if (field.FieldType.IsPrimitive || fieldValue == null) { variableNameOrValue = fieldValue?.ToString() ?? "null"; } else if (field.FieldType == typeof(string)) { variableNameOrValue = $"\"{fieldValue}\""; } else if (!context.ObjectCache.ContainsKey(fieldValue)) { Buildup(fieldValue, context); } if (variableNameOrValue == null) { variableNameOrValue = context.VariableMap[context.ObjectCache[fieldValue]]; } if (fieldVariableName == null) { context.Statements.Add(SyntaxFactory.ParseStatement($"{variableName}.{field.Name} = {variableNameOrValue};")); } else { context.Statements.Add(SyntaxFactory.ParseStatement($"{fieldVariableName}.SetValue({variableName}, {variableNameOrValue});")); } } return(variableName); }