如何序列化字段?

时间:2014-07-19 14:25:32

标签: c# serialization

我尝试编写自己的序列化程序。但是这个序列化程序只序列化属性。如何序列化字段?我所拥有的课程如下所示:

namespace MySerializer
{
class MySerializer
{
    private Type targetType;
    public MySerializer(Type targetType)
    {
        this.targetType = targetType;
        if (!targetType.IsDefined(typeof(DataContractAttribute), false))
            throw new Exception("No soup for you");
    }

    public void WriteObject(Stream stream, Object graph)
    {
        IEnumerable<PropertyInfo> serializbleProperties =
            targetType.GetProperties().Where(p => p.IsDefined(typeof (DataMemberAttribute), false));
        var writer = new StreamWriter(stream);
        writer.WriteLine("<" + targetType.Name + ">");
        foreach (PropertyInfo propInfo in serializbleProperties)
            writer.Write("\t<" + propInfo.Name + ">" + propInfo.GetValue(graph, null) +
                         "</" + propInfo.Name + ">"); 
        writer.WriteLine("</" + targetType.Name + ">");
        writer.Flush();


    }

    }
}

[DataContract]
class Person
{ 
    [DataMember]
  public  string _family;
    [DataMember]
    public string FirstName { get; set; }
    [DataMember]
    public string LastName { get; set; }
    [DataMember]
    public int Age { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Person name = new Person
        {
            _family = "big",
            FirstName = "Vasy",
            LastName = "Bobrow",
            Age = 20
        };
        MySerializer serializer = new MySerializer(name.GetType());
        MemoryStream someRam = new MemoryStream();
        serializer.WriteObject(someRam, name);
        someRam.Seek(0, SeekOrigin.Begin);
        Console.WriteLine(XElement.Parse(
            Encoding.ASCII.GetString(someRam.GetBuffer()).Replace("\0", "")));
    }
}

要序列化字段,我可以使用FieldsInfo而不是PropetryInfo,还是有另一种方式?

1 个答案:

答案 0 :(得分:3)

这个问题实际上并不是关于序列化,而是关于如何进行反思。如果要返回字段和属性,则需要使用方法GetMembers并指定要查找属性和字段。

public void WriteObject(Stream stream, Object graph)
{
    IEnumerable<MemberInfo> serializbleMembers =
        targetType.GetMembers(BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic )
                  .Where(p => p.IsDefined(typeof (DataMemberAttribute), false));
    var writer = new StreamWriter(stream);
    writer.WriteLine("<" + targetType.Name + ">");
    foreach (MemberInfo memberInfo in serializbleMembers)
    {
        writer.Write("\t<" + memberInfo.Name + ">");
        var fieldInfo = memberInfo as FieldInfo;
        if(fieldInfo != null)
        {
            writer.Write(fieldInfo .GetValue(graph, null).ToString());
        }

        var propInfo= memberInfo as PropertyInfo;
        if(propInfo != null)
        {
            writer.Write(propInfo.GetValue(graph, null).ToString());
        }

        writer.Write("</" + memberInfo.Name + ">"); 
    }
    writer.WriteLine("</" + targetType.Name + ">");
    writer.Flush();


}

但是我怀疑你的WriteObject方法非常有用,你和我的WriteObject方法都依赖于.ToString()值被覆盖(当你这样做时,你的.ToString()值隐含">" + + .ToString() [DataContract] class Example { public Example() { ExampleArray = new int[] {1, 2}; } [DataMember] int[] ExampleArray {get; set;} } 右侧的任何内容<Example> <ExampleArray>System.Int32[]</ExampleArray > </Example> 为您调用了它。例如,您尝试使用类似

的类
.ToString()

你会得到

.GetType().Name

作为输出,因为任何未覆盖{{1}}的类只会覆盖输出{{1}}。