Подтвердить что ты не робот

Есть ли сериализатор для .net, который выведет код С#?

Я ищу сериализатор, который мог бы взять экземпляр, и сериализовать его на строку, которая будет содержать код С#, представляющий содержимое графика. Класс будет функционировать аналогично SerializeObject в JSON.NET.

Я знаю, что будет работать только очень узкий набор структур, но те, которые мне интересны, довольно просты, и они будут.

Бонусные баллы, если кто-нибудь знает Visualizer Visualizer с аналогичной функциональностью.

Edit: Выход будет использоваться в другом приложении во время компиляции. Мне не нужно десериализовать вывод (код С#) во время выполнения, он сохраняется в файле для анализа.

var foo = new Foo() { Number = 1, Bar = new Bar() { Str = "Bar"}};
string sourceCode = Magic.SerializeObject(foo);

Вывод:

Foo obj = new Foo();
obj.Number = 1;
obj.RefType = null; // infer this
obj.Bar = new Bar();
obj.Bar.Str = "Bar";
4b9b3361

Ответ 1

да, и нет...

Ближайшее решение называется CodeDOM, это то, что большинство дизайнеров и мастеров Visual Studio используют для генерации кода.


После более подробного рассмотрения ваших комментариев, я думаю, вы должны внимательно прочитать раздел

Ответ 2

Написание чего-то подобного на самом деле относительно просто с помощью CodeDom:

class CSharpSerializer
{
    private readonly Dictionary<string, int> m_locals =
        new Dictionary<string, int>();

    private readonly List<CodeStatement> m_statements =
        new List<CodeStatement>();

    private string GetVariableName(string suggestedName)
    {
        suggestedName = suggestedName.TrimEnd("0123456789".ToCharArray());

        int n;
        if (m_locals.TryGetValue(suggestedName, out n))
        {
            n++;
            m_locals[suggestedName] = n;
            return suggestedName + n;
        }

        m_locals[suggestedName] = 1;
        return suggestedName;
    }

    public string SerializeObject(object obj)
    {
        m_statements.Clear();

        // dynamic used to make the code simpler
        GetExpression((dynamic)obj);

        var compiler = new CSharpCodeProvider();
        var writer = new StringWriter();
        foreach (var statement in m_statements)
        {
            compiler.GenerateCodeFromStatement(
                statement, writer, new CodeGeneratorOptions());
        }
        return writer.ToString();
    }

    private static CodeExpression GetExpression(int i)
    {
        return new CodePrimitiveExpression(i);
    }

    private static CodeExpression GetExpression(string s)
    {
        return new CodePrimitiveExpression(s);
    }

    private static CodeExpression GetExpression(DateTime dateTime)
    {
        // TODO: handle culture and milliseconds
        return new CodeMethodInvokeExpression(
            new CodeTypeReferenceExpression(typeof(Convert)), "ToDateTime",
            new CodePrimitiveExpression(Convert.ToString(dateTime)));
    }

    // and so on for other primitive types
    // and types that require special handling (including arrays)

    private CodeExpression GetExpression(object obj)
    {
        if (obj == null)
            return new CodePrimitiveExpression(null);

        var type = obj.GetType();
        string typeName = type.Name;

        string variable = GetVariableName(
            typeName[0].ToString().ToLower() + typeName.Substring(1));

        m_statements.Add(
            new CodeVariableDeclarationStatement(
                typeName, variable, new CodeObjectCreateExpression(typeName)));

        foreach (var property in type.GetProperties(
            BindingFlags.Public | BindingFlags.Instance))
        {
            var expression = GetExpression((dynamic)property.GetValue(obj));
            m_statements.Add(
                new CodeAssignStatement(
                    new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression(variable),
                        property.Name),
                    expression));
        }

        return new CodeVariableReferenceExpression(variable);
    }
}

Существует много случаев, когда этот код не сработает, но для корректных типов (публичный конструктор по умолчанию, все свойства публичного экземпляра имеют сеттеры, не имеет никакого важного состояния, скрытого в полях или непубличных свойствах, без циклических ссылок, без конфликтов пространства имен и т.д.), он будет работать.