티스토리 뷰

반응형

엡 개발시 내부에서 사용된 데이터를 저장할때 SuspensionManager를 이용하게 되는데, 데이터를 직열화를 할때 오류가 발생하게 된다. 여기서는 오류가 나는 몇가지 이유와 해결 방법들을 간단하게 살펴보기로 하겠다.

 

1. 저장방법

 

App.xaml.cs

 

        private async void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();

 

            var locator = App.Current.Resources["Locator"] as ViewModelLocator;

            //저장할 데이터의 타입을 반드시 KnownTypes에 추가해 준다.
            SuspensionManager.KnownTypes.Add(typeof(UserModel));
            //저장할 데이터를 SessionState에 추가하고
            SuspensionManager.SessionState["LoginUser"] = locator.ProfileDataVM.LoginUser;

            //SaveAsync를 호출
            await SuspensionManager.SaveAsync();

 

            deferral.Complete();
        }

 

 

2. 복구방법

 

App.xaml.cs

 

        protected override async void OnLaunched(LaunchActivatedEventArgs args)
        {

            ...

            //타입을 추가해주고
            SuspensionManager.KnownTypes.Add(typeof(UserModel));

            //SessionState 복구
            await SuspensionManager.RestoreAsync();

            var locator = App.Current.Resources["Locator"] as ViewModelLocator;

            //오브젝트로 하나 생성
            object loginUser;

            //SessionState에서 데이터 조회
            SuspensionManager.SessionState.TryGetValue("LoginUser", out loginUser);
            //데이터가 존재하면 사용

            if (loginUser != null)
            {
                locator.ProfileDataVM.LoginUser = loginUser as UserModel;
            }

            ...

        }

 

 

에러 1.

Type 'Windows.UI.Xaml.Media.ImageSource' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.  If the type is a collection, consider marking it with the CollectionDataContractAttribute.  See the Microsoft .NET Framework documentation for other supported types.

모델에 BitmapImage가 있으면 시리얼라이즈가 불가함으로 다른 방법으로 처리를 해야한다. 가장 심플한 방법은 시리얼라이즈에서 제외시키는 방법이다.

 

해결 1.

using System.Runtime.Serialization;

 

    public class UserModel : BindableBase
    {

        ...

        private BitmapImage userImage;
        /// <summary>
        /// 사용자 이미지
        /// </summary>
        [IgnoreDataMember]
        public BitmapImage UserImage
        {
            get { return userImage; }
            set
            {
                userImage = value;
                OnPropertyChanged();
            }
        }

        ...

    }

 

에러 2.

Object graph for type 'kaki104.MetroCL.Models.FolderModel' contains cycles and cannot be serialized if reference tracking is disabled

자기 자신을 참조로 가지고 있는 모델의 경우 발생하는 에러

 

해결 2.

모델의 상단에 아래 내용 추가, 만약 상속 받은 모델이 존재하는 경우 상속 받은 모델에 추가해도 됨

 

[DataContract(IsReference = true)]

public class FolderModel : BindableBase

{

    ...

}

 

에러 3.

정상적으로 저장, 복구가 되었는데 데이터가 없는 경우

 

해결 3.

프로퍼티의 내부 변수에 [DataMember] 추가

 

에러 4.

RestoreAsync() 메소드 호출시 파일이 존재하지 않아서 발생하는 오류. 파일이 없으면 그냥 Null로 떨어져야되는데 오류가 발생된다.

 

해결 4.

 

        public static async Task RestoreAsync()
        {
            _sessionState = new Dictionary<String, Object>();

            // 로컬폴더를 통째로 가지고 와서 그 안에서 파일을 찾는다.
            var files = await ApplicationData.Current.LocalFolder.GetFilesAsync();
            StorageFile file = files.FirstOrDefault(p => p.Name == sessionStateFilename);
            if (file == null)
                return;

            using (IInputStream inStream = await file.OpenSequentialReadAsync())
            {
                // Deserialize the Session State
                DataContractSerializer serializer = new DataContractSerializer(typeof(Dictionary<string, object>), _knownTypes);
                _sessionState = (Dictionary<string, object>)serializer.ReadObject(inStream.AsStreamForRead());
            }

            // Restore any registered frames to their saved state
            foreach (var weakFrameReference in _registeredFrames)
            {
                Frame frame;
                if (weakFrameReference.TryGetTarget(out frame))
                {
                    frame.ClearValue(FrameSessionStateProperty);
                    RestoreFrameNavigationState(frame);
                }
            }
        }

 

완성된 UserModel

using System;
using System.Runtime.Serialization;
using kaki104.MetroCL.Common;
using Windows.UI.Xaml.Media.Imaging;

namespace kaki104.MetroCL.Models
{

    [DataContract(IsReference = true)]
    public class UserModel : BindableBase
    {
        public UserModel()
        {
        }

 

        [DataMember]
        private string id;
        /// <summary>
        ///  아이디
        /// </summary>
        public string Id
        {
            get { return id; }
            set
            {
                id = value;
                OnPropertyChanged();
            }
        }

 

        [DataMember]
        private string name;
        /// <summary>
        /// 이름
        /// </summary>
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                OnPropertyChanged();
            }
        }

 

        [DataMember]
        private DateTime birthday;
        /// <summary>
        /// 생일
        /// </summary>
        public DateTime Birthday
        {
            get { return birthday; }
            set
            {
                birthday = value;
                OnPropertyChanged();
            }
        }

 

        private BitmapImage userImage;
        /// <summary>
        /// 사용자 이미지
        /// </summary>
        [IgnoreDataMember]
        public BitmapImage UserImage
        {
            get { return userImage; }
            set
            {
                userImage = value;
                OnPropertyChanged();
            }
        }
    }
}

 

3. 간단한 내용이라 소스를 별도로 첨부하지는 않는다.

 

반응형

'Previous Platforms > ETC' 카테고리의 다른 글

Portable Class Library Tips  (0) 2012.09.19
Windows 8 .Net 4.5 tips  (0) 2012.09.08
Windows 8 Metro app links  (0) 2012.06.12
Tips - install 3.5  (0) 2012.05.17
Windows 8 Consumer Preview Metro style app links  (0) 2012.03.11
댓글