Vlad
Vlad

Reputation: 279

How to serialize fields?

I try to write my own serializer. But this serializer serializes only properties. How to serialize fields ? Classes which I have are shown below:

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", "")));
    }
}

To serialize fields I can use FieldsInfo instead of PropetryInfo or there is another way?

Upvotes: 0

Views: 409

Answers (1)

Scott Chamberlain
Scott Chamberlain

Reputation: 127543

This question really isn't about serialization, it is more about how to do reflection. If you want to return both Fields and Properties you need to use the method GetMembers and specify that you are looking for properties and fields.

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();


}

However I doubt this your WriteObject method will be very useful, both your and my WriteObject method relies on the .ToString() value to be overridden (yours has a implicit .ToString() when you do ">" + whatever is on the right hand side of the + has .ToString() called on it for you). For example you tried to use your class on something like

[DataContract]
class Example
{
    public Example()
    {
        ExampleArray = new int[] {1, 2};
    }

    [DataMember]
    int[] ExampleArray {get; set;}
}

you would get

<Example>
    <ExampleArray>System.Int32[]</ExampleArray >
</Example>

as your output because any class that has not had .ToString() overridden just outputs .GetType().Name.

Upvotes: 3

Related Questions