Generalized Class for Tombstone


Introduction

 

This is the simplest way for tombstoning using Reflection and custom attributes. We can use this code for tombstoning your application. I hope there is no need to explain the basic idea of Reflection and Attributes but if so then please refer to (Reflection).
 

Using the code
 

The basic idea behind my code is to catch the ViewModel Classes Properties which is marked as "IsTombStone" attributes. So by using reflection we can take those properties which are marked as Tombstone Attributes. Here is the Custom Attribute Class "IsTombStoneAttribute" & AppHibernate Class for Tombstone.
 

In AppHibernate class there are two public static method œHiberNateViewModels() & œRestoreViewModel(). This HiberNateViewmodel will get all the ViewModel static instances and then get all the properties which are marked as IsTomstone attributes and save the property name and it value to Collection List for Serialization.

 

RestoreViewModel will desterilize the collection list and assign to each value to each ViewModel properties.

 

So we can call the HiberNateViewModel method inside the App.xaml.cs
 

 private void Application_Deactivated(object sender, DeactivatedEventArgs e)

        {

AppHibernate.HiberNateViewModels();

        }

To restore the tombstoned data call RestoreViewModel inside App.Xaml.cs

private void Application_Activated(object sender, ActivatedEventArgs e)

        {

AppHibernate.RestoreViewModel();

        }

 

 To Mark a property as IsTombStone Use attributes
 

For example SearchText Property in X ViewModel. We can mark this property as \

 

[IsTombStone]

Public String SearchText { get { return searchText;  }

Set { searchText=value;}

}

            //

    // Custom Attributes class   

            //

 

[AttributeUsage(AttributeTargets.Property)]

 

public class IsTombStoneAttribute:Attribute

{

public override string ToString()

{

return "IsTombStone";

}

}

       

public class KeyValue

{

#region "Properties"

 

private string viewModel;

private string key;

 

private Object valueData;

 

public string ViewModel

{

get

{

return viewModel;

}

set

{

viewModel = value;

}

}

 

public string Key

{

get

{

return key;

}

set

{

key = value;

 

}

 

}

public Object ValueData

{

get

{

return valueData;

}

set

{

valueData = value;

}

 

}

 

#endregion

 

#region "Constructor"

 

public KeyValue()

{

 

}

 

public KeyValue(string keypara, object valuepara, string viewmodelpara)

{

 

key = keypara;

valueData = valuepara;

viewModel = viewmodelpara;

}

 

#endregion

 

}

 

 /// <summary>

 

/// This General class can be used anywhere; Better to NavigateTo & NavigateFrom overide methods in codebehind

 

/// Functionality : It store the property value to xml for tombstoning; The property should marks the attributes as [IsTombStone]

 

/// </summary>

 

public class AppHibernate

{

#region Local Variables

 

private static Type[] typearray;

 

private static List<KeyValue> keyValuesList = new List<KeyValue>();

 

private const string FILENAME = "HibernateData.xml";

 

static List<Type> typList = new List<Type>();

 

#endregion

 

#region Methods

 

/// <summary>

 

/// Save the Property Value and its type

 

/// </summary>

 

/// <param name="typepara"></param>

 

/// <param name="instancepara"></param>

 

private static void HiberNate(Type typepara, object instancepara)

{

try

{

 

PropertyInfo[] propCollections = typepara.GetProperties(BindingFlags.Public | BindingFlags.Instance);

for (int i = 0; i < propCollections.Length; i++)

{

PropertyInfo myPropInfo = (PropertyInfo)propCollections[i];

object[] attributes = myPropInfo.GetCustomAttributes(true);

foreach (object attribIndx in attributes)

{

if (attribIndx.ToString() == "IsTombStone")

{

object value = myPropInfo.GetValue(instancepara, null);

if (value != null)

{

keyValuesList.Add(new KeyValue(myPropInfo.Name, value, typepara.FullName));

typList.Add(value.GetType());

}}

}

}

}

catch (Exception)

{

}

}

 

/// <summary>

 

/// Restorte the saved state

 

/// </summary>

 

/// <param name="typepara"></param>

 

/// <param name="instancepara"></param>

 

private static void RestoreState(Type typepara, object instancepara)

{

PropertyInfo[] propCollections = typepara.GetProperties(BindingFlags.Public | BindingFlags.Instance);

try

{

for (int i = 0; i < propCollections.Length; i++)

{

PropertyInfo myPropInfo = (PropertyInfo)propCollections[i];

object[] attributes = myPropInfo.GetCustomAttributes(true);

foreach (object attribIndx in attributes)

{

if (attribIndx.ToString() == "IsTombStone")

{

var count = keyValuesList.Count(x => x.Key == myPropInfo.Name);

if (count != 0)

{

var keysvalueobj = keyValuesList.First(x => x.Key == myPropInfo.Name );

object value = keysvalueobj.ValueData;

myPropInfo.SetValue(instancepara, value, null);

}}}}}

catch (Exception)

{

}

}

 

/// <summary>

 

/// Write the Property values to XML file

 

/// </summary>

 

private static void BackUp()

{

try

{

XmlSerializer SerializerObj = new XmlSerializer(typeof(List<KeyValue>), typearray);

IsolatedStorageFile iSF = IsolatedStorageFile.GetUserStoreForApplication();

 

if (iSF.FileExists(FILENAME))

{

 

iSF.DeleteFile(FILENAME);

}

 

IsolatedStorageFileStream fstream = new IsolatedStorageFileStream(FILENAME, FileMode.CreateNew, FileAccess.Write, iSF);

StreamWriter WriteFileStream = new StreamWriter(fstream);

SerializerObj.Serialize(WriteFileStream, keyValuesList);

WriteFileStream.Close();

}

catch (Exception)

{

//ErrorHandle.TraceErrorHandle("Unbale to Hibernate Data!!!");

 

}

}

 

/// <summary>

 

/// Restore Data and Assign to property

 

/// </summary>

 

private static void RestoreData()

{

keyValuesList = null;

keyValuesList = new List<KeyValue>();

if (PhoneApplicationService.Current.State.ContainsKey("types"))

{

List<string> liststringtypes = (List<string>)PhoneApplicationService.Current.State["types"];

typearray = new Type[liststringtypes.Count];

for (int Indx = 0; liststringtypes.Count > Indx; Indx++)

{

typearray[Indx] = Type.GetType(liststringtypes[Indx]);

 

}

PhoneApplicationService.Current.State.Remove("types");

}

XmlSerializer SerializerObj = new XmlSerializer(typeof(List<KeyValue>), typearray);

IsolatedStorageFile iSF = IsolatedStorageFile.GetUserStoreForApplication();

if (iSF.FileExists(FILENAME))

{

Stream ReadFileStream = new IsolatedStorageFileStream(FILENAME, FileMode.Open, FileAccess.Read, iSF);

try

{

keyValuesList = (List<KeyValue>)SerializerObj.Deserialize(ReadFileStream);

ReadFileStream.Close();

}

catch (Exception)

{}

}

}

public static void HiberNateViewModels()

{

keyValuesList.Clear();

typList.Clear();

try

{

PropertyInfo[] propCollections = typeof(ViewModelLocator).GetProperties(BindingFlags.Static | BindingFlags.Public);

for (int i = 0; i < propCollections.Length ; i++)

{

PropertyInfo myPropInfo = (PropertyInfo)propCollections[i];

object value = myPropInfo.GetValue(null, null);

HiberNate(myPropInfo.PropertyType, value);

}

if (keyValuesList.Count > 0)

{

typearray = typList.ToArray();

BackUp();

List<string> liststringtypes = new List<string>();

foreach (Type typ in typList)

{

liststringtypes.Add(typ.AssemblyQualifiedName);

}

PhoneApplicationService.Current.State.Add("types", liststringtypes);

}

}

catch (Exception)

{}

}

 

public static void RestoreViewModel()

{

RestoreData();

try

{

 

PropertyInfo[] propCollections = typeof(ViewModelLocator).GetProperties(BindingFlags.Static | BindingFlags.Public);

for (int i = 0; i < propCollections.Length ; i++)

{

PropertyInfo myPropInfo = (PropertyInfo)propCollections[i];

object value = myPropInfo.GetValue(null, null);

RestoreState(myPropInfo.PropertyType, value);

}

}

catch (Exception)

{

}}

 

#endregion

}

}


Points of Interest
 

Just Call the HiberNateViewModel & RestoreViewModel inside App class for storing the properties value to XML file. No need to Page level data store.

erver'>

Similar Articles