public ChoreographyTypeInfo GetTypeInfo(Type type)
        {
            StringBuilder typeDescription = new StringBuilder($"public class {type.Name}");
            ConcurrentDictionary <Type, ChoreographyTypeInfo> nestedTypes = new ConcurrentDictionary <Type, ChoreographyTypeInfo>();

            typeDescription.AppendLine("\n{");
            var properties = GetPropertiesDescriptions(type, nestedTypes);

            typeDescription.AppendLine(properties);
            typeDescription.AppendLine("}\n");

            foreach (var nestedType in nestedTypes.Values)
            {
                typeDescription.Append(nestedType.Object);
            }

            if (cachedTypes.TryGetValue(type, out var typeInfo))
            {
                return(typeInfo);
            }

            typeInfo = new ChoreographyTypeInfo()
            {
                Name   = type.Name,
                Object = typeDescription.ToString()
            };

            cachedTypes.TryAdd(type, typeInfo);

            return(typeInfo);
        }
        private void AddEnumDescription(Type propertyType, ConcurrentDictionary <Type, ChoreographyTypeInfo> nestedTypes)
        {
            if (propertyType.IsEnum && !propertyType.IsPrimitive && !nestedTypes.ContainsKey(propertyType))
            {
                StringBuilder typeDescription = new StringBuilder($"public enum {propertyType.Name}");
                typeDescription.AppendLine("{");

                foreach (var value in Enum.GetValues(propertyType))
                {
                    typeDescription.AppendLine($"\t{value} = {(int)value},");
                }

                typeDescription.AppendLine("}");

                var typeInfo = new ChoreographyTypeInfo()
                {
                    Name   = propertyType.Name,
                    Object = typeDescription.ToString()
                };

                nestedTypes.TryAdd(propertyType, typeInfo);
            }
        }