Click here to Skip to main content
11,719,903 members (88,312 online)
Click here to Skip to main content

Data Serializer updated for Windows Metro

, 16 Apr 2012 CPOL 6.1K 1
Rate this:
Please Sign up or sign in to vote.
Data serializer update for Windows Metro.

About a year ago I shared a simple utility class for saving serializable data on Windows Phone 7. I just updated the component for Windows 8 Metro. It still retains compatibility with Windows Phone 7 through the use of conditional compiler directives. On Windows Phone 7 I've changed the class so that it is static (so no need to instantiate it). 

For Metro the methods are asynchronous. For saving an action can be passed that will be called once the save operation is complete. When loading data you'll want to pass an action that will received the loaded data and an exception parameter that will be populated if the data could not be loaded. 

As an example of how the code works (and the platform dependent differences in its usage) here is a method from a program I have that is using the code. The program compiles on both Windows Phone 7 and Windows Metro.

public void LoadAccess()
{
#if SILVERLIGHT
    AccessInfo = DataSaver<AccessInfo>.LoadMyData("_accessToken.xml");
#endif

#if NETFX_CORE
    DataSaver<AccessInfo>.LoadDataAsync("_accessToken.xml", (info, exc)=>
    {
        if (info != null)
        {
            this.AccessInfo = info;
        }
    });
#endif
}

public void SaveAccessToken()
{
    if (this.AccessInfo != null)
    {
#if NETFX_CORE
        DataSaver<AccessInfo>.SaveMyDataAsync(this.AccessInfo, "_accessToken.xml");
#endif
#if SILVERLIGHT
       DataSaver<AccessInfo>.SaveMyData(AccessInfo, "_accessToken.xml");
#endif
    }
}

If you've never seen the #if/#endif directives before it is used to essentially conditionally comment out sections of code based on some condition. In this case the condition is certain compiler constants being defined. Some constants are automatically created for various project types. If you create a Windows Phone project the WINDOWS_PHONE and SILVERLIGHT constants are defined. For a Windows 8 Metro project the NETFX_CORE constant is defined. When you are viewing the code in the Visual Studio IDE, it will gray out any code that is going to be ignored because of the conditional compilation statements. 

Below is the code for the serializer:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;

using System.IO;
#if SILVERLIGHT
using System.IO.IsolatedStorage;
#endif

#if NETFX_CORE
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
#endif

namespace J2i.Net.Utility
{


    public class DataSaver<MyDataType>
    {

        static List<Type> _knownTypeList = new List<Type>();
        public static List KnownTypeList
        {
            get
            {
                return _knownTypeList;
            }
        }
#if SILVERLIGHT
        private static IsolatedStorageFile _isoFile;
        static IsolatedStorageFile IsoFile
        {
            get
            {
                if (_isoFile == null)
                    _isoFile = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
                return _isoFile;
            }
        }

         public static void SaveMyData(MyDataType sourceData, String targetFileName)
        {
            try
            {
                using (var targetFile = IsoFile.CreateFile(targetFileName))
                {
                    var d = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                    d.WriteObject(targetFile, sourceData);
                }
            }
            catch (Exception )
            {
                IsoFile.DeleteFile(targetFileName);
            }
        }


        public static MyDataType LoadMyData(string sourceName)
        {
            MyDataType retVal = default(MyDataType);
            if (IsoFile.FileExists(sourceName))
                using (var sourceStream = IsoFile.OpenFile(sourceName, FileMode.Open))
                {
                    var d = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                    retVal = (MyDataType)d.ReadObject(sourceStream);
                }
            return retVal;
        }
#endif
        public DataSaver()
        {
        }
#if NETFX_CORE
        public static async void SaveMyDataAsync(
            MyDataType sourceData, 
            String targetFileName, 
            Action<MyDataType,String, Exception> OnSaved = null)
        {
            try
            {
                StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
                    targetFileName, CreationCollisionOption.ReplaceExisting
                    );
                IRandomAccessStream raStream = await file.OpenAsync(FileAccessMode.ReadWrite);
                IOutputStream outStream = raStream.GetOutputStreamAt(0);

                DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                serializer.WriteObject(outStream.AsStreamForWrite(), sourceData);
                await outStream.FlushAsync();
                if(OnSaved!=null)
                    OnSaved(sourceData, targetFileName, null);
            }
            catch (Exception exc)
            {
                if (OnSaved != null)
                {
                    OnSaved(sourceData, targetFileName, exc);
                }
            }
        }

        public static async void LoadDataAsync(string fileName, 
               Action<MyDataType, Exception> loadAction)
        {
            if (loadAction == null)
                return;
            try
            {
                StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
                if (file == null) return;
                IInputStream inStream = await file.OpenSequentialReadAsync();

                // Deserialize the Session State. 
                DataContractSerializer serializer = 
                   new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                MyDataType data = (MyDataType)serializer.ReadObject(inStream.AsStreamForRead());
                loadAction(data, null);
            }
            catch (Exception e)
            {
                loadAction(default(MyDataType), e);
            }
        }
#endif

    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Joel Ivory Johnson
Software Developer Razorfish
United States United States
I attended Southern Polytechnic State University and earned a Bachelors of Science in Computer Science and later returned to earn a Masters of Science in Software Engineering.

For the past few years I've been providing solutions to clients using Microsoft technologies for web and Windows applications.

While most of my CodeProject.com articles are centered around Windows Phone it is only one of the areas in which I work and one of my interests. I also have interest in mobile development on Android and iPhone. Professionally I work with several Microsoft technologies including SQL Server technologies, Silverlight/WPF, ASP.Net and others. My recreational development interest are centered around Artificial Inteligence especially in the area of machine vision.

Twitter:@J2iNet

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150901.1 | Last Updated 16 Apr 2012
Article Copyright 2012 by Joel Ivory Johnson
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid