我在 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
}