Thursday, June 5, 2008

Sample of attribute usage in c# (csharp).

        To show usage of attribute let’s write method, which pass all fields of a object and if a field has attribute [NonSerialized], then the method will copy value into the field from second object. The method can be used to restore unserialized fields from original object.

Sample:

Class:

[Serializable]
public class FooClass
{
public int data1;
[NonSerialized] public int data2;
public FooClass(int data1, int data2)
{
this.data1 = data1;
this.data2 = data2;
}
}



Usage:



FooClass destObject = new FooClass(10, 20);
FooClass sourceObject = new FooClass(10, 30);

Debug.Print("destObject.data2: {0}, sourceObject.data2: {1}", destObject.data2, sourceObject.data2);

RestoreUtils.RestoreNonSerialized(destObject, sourceObject);

Debug.Print("destObject.data2: {0}, sourceObject.data2: {1}", destObject.data2, sourceObject.data2);



Output:



output



We can see, that method RestoreUtils.RestoreNonSerialized restored values of destObject field data2 from sourceObject.





Sources of RestoreUtils.RestoreNonSerialized



using System;
using System.Reflection;
using System.Collections;

namespace ReflectionServices
{
public class RestoreUtils
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;

public static void RestoreNonSerialized(object dest, object source)
{
if (dest == null || source == null)
return;

Type objectType = dest.GetType();
if (objectType.IsPrimitive | objectType.IsValueType)
return;

FieldInfo[] dstFieldsInfo = objectType.GetFields(flags);
FieldInfo[] srcFieldsInfo = source.GetType().GetFields(flags);

for (int fieldIndex = 0; fieldIndex < dstFieldsInfo.Length; fieldIndex++)
{
FieldInfo fieldInfo = dstFieldsInfo[fieldIndex];
if (fieldInfo.IsNotSerialized)
{
object newValue = srcFieldsInfo[fieldIndex].GetValue(source);
fieldInfo.SetValue(dest, newValue);
continue;
}

object dstFieldObject = fieldInfo.GetValue(dest);
object srcFieldObject = srcFieldsInfo[fieldIndex].GetValue(source);
if (dstFieldObject != null && srcFieldObject != null)
RestoreNonSerialized(dstFieldObject, srcFieldObject);
}

IEnumerable dstEnumerable = dest as IEnumerable;
if (dstEnumerable != null)
{
IEnumerable srcEnumerable = source as IEnumerable;
if (srcEnumerable != null)
{
IEnumerator srcEnumerator = srcEnumerable.GetEnumerator();
foreach (Object dstItem in dstEnumerable)
{
bool next = srcEnumerator.MoveNext();
if (!next)
break;
Object srcItem = srcEnumerator.Current;

RestoreNonSerialized(dstItem, srcItem);
}
}
}
}
}
}


Reference:



Attributes (C# Programming Guide)



 

How to serialize c# object to binary data.

       The simplest way to serialize object, that is use class BinaryFormatter.

Sample of serialization to file:

using (FileStream stream = new FileStream(tempFilePath, FileMode.Create))
{
BinaryFormatter b = new BinaryFormatter();
b.Serialize(stream, originalData);
}




Sample of deserialization to file:



Data actualData;
using (FileStream stream = new FileStream(tempFilePath, FileMode.Open))
{
BinaryFormatter b = new BinaryFormatter();
actualData = (Data)b.Deserialize(stream);
}


where class Data has attribute [Serializable].



See sources on “C# tips samples” project.



Reference:



BinaryFormatter Class



The simplest way to store object to .xml file in c#.