Created
September 26, 2016 03:35
-
-
Save MichaelLHerman/d9b7e8cf8e2adc43e2d29dade20f5f09 to your computer and use it in GitHub Desktop.
Generates code to generate objects using C# Object Initializer syntax
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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