Autofac SingleInstance() 和 Xamarin Forms
Autofac SingleInstance() and Xamarin Forms
首先,让我说一下,我在这里阅读了几个关于 SingleInstance 的问题,但仍然找不到对我有帮助的直接答案。也就是说,如果我遗漏了什么,我深表歉意。
这是我的问题:
我正在为 iOS 和 Android 构建 Xamarin Forms 应用程序。我在 PCL 中有一个 AppInitializer class,我在其中使用 Autofac 注册了所有接口依赖项。然后,我将构建器中的容器分配为应用 class 上的静态 属性。我遇到的问题是,当我使用 .SingleInstance() 注册所有内容时,我实际上并没有获得单个实例。
初始化逻辑示例:
var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
我让 Autofac 在我的构造函数中处理解析接口。例如:
public MemberViewModel(ISettingsViewModel settings, IErrorHandler errorHandler, …) : base(settings, errorHandler){…}
然后我在页面上使用所述模型如下:
页面使用示例:
public ProfilePage()
{
InitializeComponent();
var displayModel = Model.CurrentMember;
…
}
…
**public IMemberViewModel Model =>
AppContainer.Current.Resolve<IMemberViewModel>();**
在此示例中,我在到达此页面之前立即设置了 Model.CurrentMember 的属性。我已经设置了断点并且知道这正在发生。但是,当我解析模型的实例时,CurrentMember 上的属性为空。
我是不是做错了什么,还是遇到了错误?
-编辑-
明确表示我正在使用 Autofac。
-编辑2-
添加更多详细信息。
我的 IMemberViewModel class 实现具有各种属性,包括称为当前成员的可观察对象。声明如下:
public class MemberViewModel : ViewModelBase, IMemberViewModel
{
…
(see constructor above)
…
public MemberDisplay CurrentMember =>
m_CurrentMember ?? (m_CurrentMember = new MemberDisplay())
关于 IMemberViewModel 的实现,我有一个方法可以设置 CurrentMember 的各种属性。
操作顺序是这样的:
最终用户点击成员的图像。这会在 IMemberViewModel 实现的(理论上)单例实例上触发一个命令。此命令执行一个异步任务,该任务等待对 API 的异步调用以加载该成员的数据。在加载该数据并在 CurrentMember 上设置属性后,应用程序导航到配置文件屏幕。配置文件屏幕解析 IMemberViewModel(根据上述)。
预期行为:
已解析的 IMemberViewModel 实例的 CurrentMember 属性设置为刚刚从加载数据方法设置的值。这种预期源于假设存在一个 IMemberViewModel 实例。
实际行为:
CurrentMember 的属性处于默认值,即 string.Empty、0、null 等
奇怪的是,并不是每个模型都会出现这种情况。我有一个消息模型,我在同一个屏幕上以相同的方式解析它似乎没问题。
这个问题原来是由我们初始化所有内容的方式引起的。为了后代,我将简要说明正在发生的事情以及我为防止它所做的工作。
之前的应用流程:
- 应用打开并调用构造函数。这会调用上面的初始化例程。
- 用户登录。
- IMemberViewModel 的第一个实例使用静态容器解析。
- 弹出一条消息,询问用户推送通知权限
- 发生这种情况时,将调用应用程序 OnSleep (iOS)
- 用户选择答案后,将调用 OnResume。
- OnResume 调用初始化例程
- 已创建新 容器。
- 加载数据的调用发生在旧容器上,新页面引用新容器。
- 出现如上所述的问题。
修正流量:
首先,据我所知,如果在应用程序构造函数中进行初始化调用,则不需要在恢复时进行 and/or 启动。如果该应用 "killed" 因为其他应用需要内存 space,将在下次启动时创建该应用的新版本(请参阅 Android Activity Lifecycle and the iOS App Lifecycle)。
其次,因为我偏执,因为它不会伤害,在应用程序初始化例程中,我现在正在检查以确定容器是否存在以及接口是否已经注册。
public static void Init(ISetup setup)
{
if (Container != null && IsModelRegistered()) return;
RegisterDependencies(setup);
…
}
private static bool IsModelRegistered()
{
return Container.IsRegistered<IMemberViewModel>();
}
首先,让我说一下,我在这里阅读了几个关于 SingleInstance 的问题,但仍然找不到对我有帮助的直接答案。也就是说,如果我遗漏了什么,我深表歉意。
这是我的问题:
我正在为 iOS 和 Android 构建 Xamarin Forms 应用程序。我在 PCL 中有一个 AppInitializer class,我在其中使用 Autofac 注册了所有接口依赖项。然后,我将构建器中的容器分配为应用 class 上的静态 属性。我遇到的问题是,当我使用 .SingleInstance() 注册所有内容时,我实际上并没有获得单个实例。
初始化逻辑示例:
var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
我让 Autofac 在我的构造函数中处理解析接口。例如:
public MemberViewModel(ISettingsViewModel settings, IErrorHandler errorHandler, …) : base(settings, errorHandler){…}
然后我在页面上使用所述模型如下:
页面使用示例:
public ProfilePage()
{
InitializeComponent();
var displayModel = Model.CurrentMember;
…
}
…
**public IMemberViewModel Model =>
AppContainer.Current.Resolve<IMemberViewModel>();**
在此示例中,我在到达此页面之前立即设置了 Model.CurrentMember 的属性。我已经设置了断点并且知道这正在发生。但是,当我解析模型的实例时,CurrentMember 上的属性为空。
我是不是做错了什么,还是遇到了错误?
-编辑- 明确表示我正在使用 Autofac。
-编辑2- 添加更多详细信息。
我的 IMemberViewModel class 实现具有各种属性,包括称为当前成员的可观察对象。声明如下:
public class MemberViewModel : ViewModelBase, IMemberViewModel
{
…
(see constructor above)
…
public MemberDisplay CurrentMember =>
m_CurrentMember ?? (m_CurrentMember = new MemberDisplay())
关于 IMemberViewModel 的实现,我有一个方法可以设置 CurrentMember 的各种属性。
操作顺序是这样的:
最终用户点击成员的图像。这会在 IMemberViewModel 实现的(理论上)单例实例上触发一个命令。此命令执行一个异步任务,该任务等待对 API 的异步调用以加载该成员的数据。在加载该数据并在 CurrentMember 上设置属性后,应用程序导航到配置文件屏幕。配置文件屏幕解析 IMemberViewModel(根据上述)。
预期行为: 已解析的 IMemberViewModel 实例的 CurrentMember 属性设置为刚刚从加载数据方法设置的值。这种预期源于假设存在一个 IMemberViewModel 实例。
实际行为: CurrentMember 的属性处于默认值,即 string.Empty、0、null 等
奇怪的是,并不是每个模型都会出现这种情况。我有一个消息模型,我在同一个屏幕上以相同的方式解析它似乎没问题。
这个问题原来是由我们初始化所有内容的方式引起的。为了后代,我将简要说明正在发生的事情以及我为防止它所做的工作。
之前的应用流程:
- 应用打开并调用构造函数。这会调用上面的初始化例程。
- 用户登录。
- IMemberViewModel 的第一个实例使用静态容器解析。
- 弹出一条消息,询问用户推送通知权限
- 发生这种情况时,将调用应用程序 OnSleep (iOS)
- 用户选择答案后,将调用 OnResume。
- OnResume 调用初始化例程
- 已创建新 容器。
- 加载数据的调用发生在旧容器上,新页面引用新容器。
- 出现如上所述的问题。
修正流量:
首先,据我所知,如果在应用程序构造函数中进行初始化调用,则不需要在恢复时进行 and/or 启动。如果该应用 "killed" 因为其他应用需要内存 space,将在下次启动时创建该应用的新版本(请参阅 Android Activity Lifecycle and the iOS App Lifecycle)。
其次,因为我偏执,因为它不会伤害,在应用程序初始化例程中,我现在正在检查以确定容器是否存在以及接口是否已经注册。
public static void Init(ISetup setup)
{
if (Container != null && IsModelRegistered()) return;
RegisterDependencies(setup);
…
}
private static bool IsModelRegistered()
{
return Container.IsRegistered<IMemberViewModel>();
}