Вопрос

I have next code:

public static class AppUser
    {
        static AppUser()
        {
            RestorePreviewUserState();
        }

        private static void RestorePreviewUserState()
        {
            var storedToken = Settings.Authentification.SessionToken; //Here I gets my settings
            var storedUserId = Settings.Authentification.CurrentUserId; 

            if (storedToken == null || storedUserId == default(int)) return;
            AuthToken = storedToken;
            CurrentUserId = storedUserId;
        }

        public static bool ExistAuthData
        {
            get
            {
                return CurrentUserId != default(int) && AuthToken != null;
            }
        }

        private static string _authToken;
        public static string AuthToken
        {
            get { return _authToken; }
            set
            {
                _authToken = value;
                Settings.Authentification.SessionToken = _authToken;
                AuthHeader = new AuthHeader(_authToken);
            }
        }

        private static int _currentUserId;
        public static int CurrentUserId
        {
            get { return _currentUserId; }
            set
            {
                _currentUserId = value;
                Settings.Authentification.CurrentUserId = _currentUserId;
            }
        }
    }


    public class LocalSettings : ILocalSettings
    {
        public T GetValue<T>(string key)
        {
            if (ApplicationData.Current.LocalSettings.Values.ContainsKey(key))
                return (T)ApplicationData.Current.LocalSettings.Values[key];

            return default(T);
        }

        public void SetValue(string key, object value)
        {
            if (value == null)
                ApplicationData.Current.LocalSettings.Values.Remove(key);

            ApplicationData.Current.LocalSettings.Values[key] = value;
        }
    }

    public interface ILocalSettings
    {
        T GetValue<T>(string key);
        void SetValue(string key, object value);
    }

    public static class Settings
    {
        private static readonly ILocalSettings _settings;

        static Settings()
        {
            _settings = new LocalSettings();
        }

        public static class Authentification
        {
            private const string CurrentUserKey = "CurrentUserId";
            public static int CurrentUserId
            {
                get { return _settings.GetValue<int>(CurrentUserKey); }
                set { _settings.SetValue(CurrentUserKey, value); }
            }

            private const string SessionTokenKey = "SessionToken";
            public static string SessionToken
            {
                get { return _settings.GetValue<string>(SessionTokenKey); }
                set { _settings.SetValue(SessionTokenKey, value); }
            }
        }
    }

When my app starts, I try to check if ExistAuthData in AppUser

if (!AppUser.ExistAuthData)
            {
                ...
            }

And it throw me exception:

'AppUser.ExistAuthData' threw an exception of type 'System.TypeInitializationException'

But when I try to get value before AppUser.ExistAuthData every things fine:

var temp = ApplicationData.Current.LocalSettings.Values.ContainsKey("Anykey");
if (!AppUser.ExistAuthData)

Why it's happening?

UPD

 at System.StubHelpers.StubHelpers.GetWinRTFactoryObject(IntPtr pCPCMD)
   at Windows.Storage.ApplicationData.get_Current()
   at EventsNotifier.Helpers.LocalSettings.GetValue[T](String key) in e:\New projects\Events\EventsNotifier\EventsNotifier\Helpers\Settings.cs:line 9
   at EventsNotifier.Helpers.Settings.Authentification.get_SessionToken() in e:\New projects\Events\EventsNotifier\EventsNotifier\Helpers\Settings.cs:line 70
   at EventsNotifier.Helpers.AppUser.RestorePreviewUserState() in e:\New projects\Events\EventsNotifier\EventsNotifier\Helpers\AppUser.cs:line 13
   at EventsNotifier.Helpers.AppUser..cctor() in e:\New projects\Events\EventsNotifier\EventsNotifier\Helpers\AppUser.cs:line 8
Это было полезно?

Решение

I tried reproducing your issue and I only managed to reproduce it while debugging it:

  • Even if AppUser.ExistAuthData was the first call in App constructor, it worked fine as long as I didn't put any breakpoints before the call.
  • If I put the breakpoint before the call and hovered over the AppUser.ExistAuthData property, I managed to reproduce your error with the exact same stack trace.

The reason seems to be that if you try to initialize LocalSettings (first call) while the main thread is stopped, it throws an exception (you can see that even in the debugger tooltip). As soon as this happens, there's no way to use AppUser class any more, because the exception was thrown from its static constructor which is called only a single time and rethrows the same exception at any future attempt to acces it. I've already blogged about this behavior years ago.

If you access LocalSettings before that call, you have already initialized it, making sure future attempts to access it don't fail even if the main thread is stopped. This way, everything works fine even if you hover over the property in the debugger.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top