예제 #1
0
        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));
        }
예제 #2
0
        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);
        }