static void AddIndentHelpers(CodeTypeDeclaration type)
        {
            var zero = Expression.Primitive(0);

            type.AddPropertyGetOnly("CurrentIndent",
                                    type.AddField("currentIndent", TypeReference.String, init: Expression.StringEmpty)
                                    .WithReference(out var currentIndent));

            type.AddProperty <Stack <int> > ("Indents").AsPrivate()
            .WithGetLazyInitialize(
                type.AddField <Stack <int> > ("indents"),
                Expression.New <Stack <int> > ())
            .WithReference(out var indents);

            type.AddMethod("PopIndent").Returns <string> ()
            .WithStatements(
                Statement.If(indents.Property("Count").IsEqualValue(zero),
                             Then: Expression.StringEmpty.Return()),
                Statement.DeclareVariable <int> ("lastPos",
                                                 currentIndent.Property("Length").Subtract(indents.InvokeMethod("Pop")),
                                                 out var lastPosRef),
                Statement.DeclareVariable(TypeReference.String, "last",
                                          currentIndent.InvokeMethod("Substring", lastPosRef),
                                          out var lastRef),
                currentIndent.Assign(currentIndent.InvokeMethod("Substring", zero, lastPosRef)),
                lastRef.Return()
                );

            type.AddMethod("PushIndent")
            .WithParameter("indent", TypeReference.String, out var paramIndent)
            .WithStatements(
                indents.InvokeMethod("Push", paramIndent.Property("Length")).AsStatement(),
                currentIndent.Assign(currentIndent.Add(paramIndent))
                );

            type.AddMethod("ClearIndent")
            .WithStatements(
                currentIndent.Assign(Expression.StringEmpty),
                indents.InvokeMethod("Clear").AsStatement()
                );
        }
        static void AddToStringHelper(CodeTypeDeclaration type, CodeDomProvider provider)
        {
            var helperClass = Declare.Class("ToStringInstanceHelper")
                              .AsNestedPublic()
                              .WithReference(out var helperClassType);

            helperClass.AddField <IFormatProvider> ("formatProvider",
                                                    TypeReference <System.Globalization.CultureInfo> .Global.Property("InvariantCulture"))
            .WithReference(out var formatProvider);

            helperClass.AddProperty <IFormatProvider> ("FormatProvider")
            .WithGet(formatProvider)
            .WithSetIgnoresNull(formatProvider);

            helperClass.AddMethod("ToStringWithCulture")
            .Returns <string> ()
            .WithParameter <object> ("objectToConvert", out var objectToConvert)
            .WithStatements(
                objectToConvert.ThrowIfNull(),
                Declare.Variable <Type> ("type", objectToConvert.InvokeMethod("GetType"), out var objType),
                Declare.Variable <Type> ("iConvertibleType", Expression.TypeOf <IConvertible> (), out var iConvertibleType),
                Statement.If(iConvertibleType.InvokeMethod("IsAssignableFrom", objType),
                             Then: Statement.Return(objectToConvert.Cast <IConvertible> ().InvokeMethod("ToString", formatProvider))),
                Declare.Variable <System.Reflection.MethodInfo> ("methInfo",
                                                                 objType.InvokeMethod("GetMethod", Expression.Primitive("ToString"), Expression.Array <Type> (iConvertibleType)),
                                                                 out var methInfoLocalRef),
                Statement.If(methInfoLocalRef.IsNotNull(),
                             Then: Statement.Return(Expression.Cast <string> (
                                                        methInfoLocalRef.InvokeMethod("Invoke", objectToConvert, Expression.Array <object> (formatProvider))))),
                Statement.Return(objectToConvert.InvokeMethod("ToString"))
                );

            var helperFieldName = provider.CreateValidIdentifier("_toStringHelper");

            type.AddPropertyGetOnly("ToStringHelper",
                                    type.AddField(helperFieldName, helperClassType, Expression.New(helperClassType)));

            type.AddMember(helperClass);
        }