是否有.net的序列化器将输出c#代码?

时间:2013-04-16 23:01:56

标签: c# .net serializer

我正在寻找一个可以接受实例的序列化程序,并将其序列化为包含c#代码的字符串,表示图形的内容。 该类的功能类似于JSON.NET中的SerializeObject

我知道只有一组非常狭窄的结构可以使用,但我感兴趣的结构很简单,他们会这样做。

如果有人知道具有类似功能的Visual Studio Visualizer,则获得积分。

修改 输出将在编译时用于不同的应用程序。我不需要在运行时反序列化输出(c#代码),它会保存到文件中进行分析。

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";

2 个答案:

答案 0 :(得分:6)

是的,没有......

最接近的解决方案称为CodeDOM,它是大多数Visual Studio设计人员和向导用来生成代码的。


在仔细查看您的评论后,我认为您应该仔细阅读MSDN中的Binary Serialization部分,它将满足您的所有要求。

您要查找的是序列化,您不希望每次都重新编译第二个项目吗? 您只需要验证,并转发\ back 兼容性

答案 1 :(得分:3)

使用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);
    }
}

在许多情况下,此代码将失败,但对于行为良好的类型(公共默认构造函数,所有公共实例属性都有setter,没有隐藏在字段或非公共属性中的重要状态,没有循环引用,没有命名空间冲突等等),它会起作用。