我在 WinRt 中使用 C# 和 SQLite 从 Windows 应用商店应用程序调用 WinRt 类库...对象在意外时间返回空引用错误...
我正在尝试实现一个登录服务,通过检查数据文件是否存在来检查当前用户是否已经登录,然后检查用户是否是当前登录的用户......
用户只需输入他们的 ID 并单击登录按钮即可。它创建一个包装 SQLite 数据库的 DataService 对象,然后将其“注入”到 UserStartupService 中。
UserStartupService 使用依赖注入、单例并实现 IDisposable。
问题 1)如果用户再次单击登录按钮,则 UserStartupService 对象构造函数不会运行,并且当使用内部对象时,即使它在退出 using 块后通过 dispose 方法运行,也会引发空引用错误,这迫使我停用登录按钮,这充其量是一个kluge修复。新用户必须退出程序才能以新用户身份登录。(原始代码没有实现 IAsyncOperationWithProgress,但这应该没关系...)
问题 2)我现在正在尝试实现 IAsyncOperationWithProgress 以将进度传递回 UI,并且在尝试在线使用 _dataFeedService 时会收到空引用错误:
var json = await _dataFeedService.ValidateUser(userId);
即使它按预期在 using 语句的顶部运行构造函数......
我认为这里缺少一个范围/线程问题。也许有什么明显的...
有任何想法吗?谢谢!
// logon button pressed...
private void LogOn_Click(object sender, RoutedEventArgs e)
{
    // Create database service for DI
    DataService _dataService = new DataService("MyData.sqlite");
    // using statement for scope control
    using (UserStartupService uss = UserStartupService.GetInstance(_dataService))
    {
        // progress bar...
        CurrentProgress.Visibility = Windows.UI.Xaml.Visibility.Visible;
        // create op and call...
        IAsyncOperationWithProgress<string, int> op;
        op = uss.SetUpUser(txtUserId.Text);
        op.Progress = (info, progress) =>
        {
            CurrentProgress.Value = progress;
        };
        op.Completed = (info, status) =>
        {
            var results = info.GetResults();
            // when completed...
            if (status == AsyncStatus.Completed)
            {
                txtMessage.Text = "Current user data already loaded...";
                CurrentProgress.Value = 100;
            } // if cancelled...
            else if (status == AsyncStatus.Canceled)
            {
                // Operation canceled - not implemented...
            }
        };
    }
    btnLogon.IsEnabled = false;
}
public sealed class UserStartupService : IDisposable
{
    #region properties
    // services
    private static DataService _dataService;
    private static DataFeedService _dataFeedService;
    private static SqliteService _sqlMAFService;
    private static SerialiseDeserialiseService _serializeService;
    private string _token = String.Empty;
    #endregion properties
    #region constructors with DI and singleton pattern
    // use this code to implement singleton patter...
    // private constructor = can't instance without GetInstance...
    private UserStartupService(DataService dataService)
    {
        // guard clause...
        if (dataService == null)
        {
            throw new ArgumentNullException("DataService");
        }
        _dataService = dataService;
        _dataFeedService = new DataFeedService();
        _sqlMAFService = new SqliteService(_dataService);
        _serializeService = new SerialiseDeserialiseService();
    }
    // implement singleton
    public static UserStartupService GetInstance(DataService dataService)
    {
        _dataService = dataService;
        return MyNestedSingletonClass.singleton;
    }
    class MyNestedSingletonClass
    {
        internal static readonly UserStartupService singleton = new UserStartupService(_dataService);
        static MyNestedSingletonClass() { }
    }
    #endregion constructors with DI and singleton pattern
    public IAsyncOperationWithProgress<string, int> SetUpUser(string userId)
    {
        return AsyncInfo.Run<string, int>((token, progress) =>
            Task.Run<string>(async () =>
            {
                progress.Report(1);
                try
                {
                    // validate user against server REST feed and get token
                    var json = await _dataFeedService.ValidateUser(userId);
                                                        // ... it never gets here due to _dataFeedService null exception
                    // ...more code ... never gets here...
                }
                catch (Exception ex)
                {
                    return ex.Message;
                }
                progress.Report(100);
                return "";
            }, token));
    }
    #region implement IDisposable
    public void Dispose()
    {
        _serializeService = null;
        _sqlMAFService.Dispose();
        _sqlMAFService = null;
        _dataFeedService.Dispose();
        _dataFeedService = null;
        _dataService.CloseConnection();
        _dataService = null;
    }
    #endregion implement IDisposable
}