Skip to content

Instantly share code, notes, and snippets.

@MichaelLHerman
Created September 26, 2016 03:35
Show Gist options
  • Save MichaelLHerman/d9b7e8cf8e2adc43e2d29dade20f5f09 to your computer and use it in GitHub Desktop.
Save MichaelLHerman/d9b7e8cf8e2adc43e2d29dade20f5f09 to your computer and use it in GitHub Desktop.
Generates code to generate objects using C# Object Initializer syntax
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ObjectInitializerCodeGenerator
{
public class CodeGenerator
{
private CodeGenerator()
{
}
public static string GetFriendlyTypeName(Type type)
{
if (type.IsGenericParameter) { return type.Name; }
if (!type.IsGenericType) { return type.FullName; }
var builder = new System.Text.StringBuilder();
var name = type.Name;
var index = name.IndexOf("`");
builder.AppendFormat("{0}.{1}", type.Namespace, name.Substring(0, index)); builder.Append('<');
var first = true;
foreach (var arg in type.GetGenericArguments())
{
if (!first) { builder.Append(','); }
builder.Append(GetFriendlyTypeName(arg)); first = false;
}
builder.Append('>');
return builder.ToString();
}
private string GenerateCodeInternal(object input)
{
var variableType = input.GetType();
var variableName = CreateVariableName(variableType);
sb.Append("var ");
sb.Append(variableName);
//TODO: better check
if (variableType.IsClass && variableType != typeof(string))
{
sb.Append(" = new ");
sb.Append(GetFriendlyTypeName(variableType));
sb.AppendLine("();");
//if (variableType.GetInterfaces().Contains(typeof(System.Collections.IList)))
var asList = input as System.Collections.IList;
if (asList != null)
{
foreach (var element in asList)
{
var elementName = GenerateCodeInternal(element);
sb.Append(variableName);
sb.Append(".Add(");
sb.Append(elementName);
sb.AppendLine(");");
}
}
else
{
foreach (PropertyInfo pi in variableType.GetProperties())
{
var propertyValue = pi.GetValue(input, null);
if (pi.PropertyType.IsValueType)
{
//if not default
if (!object.Equals(Activator.CreateInstance(pi.PropertyType), propertyValue))
{
sb.Append(variableName);
sb.Append(".");
sb.Append(pi.Name);
sb.Append(" = ");
sb.Append(propertyValue); //does not work for Decimal
sb.AppendLine(";");
}
}
else
{
if (propertyValue != null)
{
if (pi.PropertyType == typeof(String))
{
sb.Append(variableName);
sb.Append(".");
sb.Append(pi.Name);
sb.Append(" = \"");
sb.Append(propertyValue);
sb.AppendLine("\";");
}
//collection
else
{
//warn if no constructor
if (pi.PropertyType.GetConstructor(System.Type.EmptyTypes) == null)
sb.AppendLine("//Warning - no parameterless constructor. Will not compile");
//recurse
var objectName = GenerateCodeInternal(propertyValue);
sb.Append(variableName);
sb.Append(".");
sb.Append(pi.Name);
sb.Append(" = ");
sb.Append(objectName);
sb.AppendLine(";");
}
}
}
//
//var propname = GenerateCodeInternal(pi.GetValue(input, null));
}
}
}
//else if (variableType.IsValueType)
//{
// sb.Append(" = ");
// sb.Append(input);
// sb.AppendLine(";");
//}
return variableName;
}
const string spaces = " ";
private string GenerateObjectInitializerCodeInternal(object input, int indent = 0)
{
StringBuilder sb = new StringBuilder();
var variableType = input.GetType();
if (variableType.IsValueType)
{
sb.Append(input.ToString()); //does not work for Decimal
}
else if (variableType == typeof(String))
{
sb.Append("\"");
sb.Append(input.ToString());
sb.Append("\"");
}
else if (variableType.IsClass)
{
sb.Append("new ");
sb.Append(GetFriendlyTypeName(variableType));
//if (variableType.GetInterfaces().Contains(typeof(System.Collections.IList)))
var list = input as System.Collections.IList;
if (list != null)
{
sb.AppendLine("{");
var listItems = new List<String>();
foreach (object item in list)
{
listItems.Add(new String('\t', indent + 1) + GenerateObjectInitializerCodeInternal(item, indent + 1));
}
if (listItems.Count > 0)
{
sb.AppendLine(String.Join(", \n", listItems));
}
sb.Append(new String('\t', indent) + "}");
}
else
{
sb.Append("()");
var props = new List<String>();
foreach (PropertyInfo pi in variableType.GetProperties())
{
if (pi.PropertyType.IsValueType)
{
var propertyValue = pi.GetValue(input, null);
//if not default
if (!object.Equals(Activator.CreateInstance(pi.PropertyType), propertyValue))
{
props.Add(new String('\t', indent + 1) + pi.Name + " = " + GenerateObjectInitializerCodeInternal(propertyValue, indent + 1));
}
}
else
{
var propertyValue = pi.GetValue(input, null);
if (propertyValue != null)
{
props.Add(new String('\t', indent + 1) + pi.Name + " = " + GenerateObjectInitializerCodeInternal(propertyValue, indent + 1));
}
}
}
if (props.Count > 0)
{
sb.AppendLine(" { ");
sb.AppendLine(String.Join(", \n", props));
sb.Append(new String('\t', indent) + "}");
}
}
}
return sb.ToString();
}
StringBuilder sb = new StringBuilder();
public static string GenerateCode<T>(T input) where T : new()
{
CodeGenerator cg = new CodeGenerator();
cg.GenerateCodeInternal(input);
return cg.sb.ToString();
}
public static string GenerateObjectInitializerCode<T>(T input) where T : new()
{
CodeGenerator cg = new CodeGenerator();
return cg.GenerateObjectInitializerCodeInternal(input);
}
Dictionary<Type, int> variableNameCounter = new Dictionary<Type, int>();
public string CreateVariableName(Type t)
{
if (!variableNameCounter.ContainsKey(t))
{
variableNameCounter.Add(t, 0);
return t.Name.ToCamelCase() + "0";
}
else
{
var count = variableNameCounter[t]++;
return t.Name.ToCamelCase() + count;
}
}
}
public static class Extentions
{
public static string ToCamelCase(this string input)
{
if (input == null) return null;
if (input == String.Empty) return String.Empty;
if (input.Length == 1) return input.ToLower();
return Char.ToLower(input[0]).ToString() + input.Substring(1);
}
}
public class Formatter : IFormatProvider
{
public object GetFormat(Type formatType)
{
throw new NotImplementedException();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment