Xamarin.forms Autofac SingleInstance()和Xamarin表单

Xamarin.forms Autofac SingleInstance()和Xamarin表单,xamarin.forms,autofac,single-instance,Xamarin.forms,Autofac,Single Instance,首先,我要说的是,我在这里已经阅读了几个关于SingleInstance的问题,但仍然找不到一个对我有帮助的直接答案。也就是说,如果我错过了什么,我道歉 我的问题是: 我正在为iOS和Android构建一个Xamarin表单应用程序。我在PCL中有一个单一的AppInitializer类,在这里我使用Autofac注册所有接口依赖项。然后,我将构建器中的容器指定为app类的静态属性。我遇到的问题是,当我使用.SingleInstance()注册所有内容时,实际上并没有得到一个实例 初始化逻辑示例

首先,我要说的是,我在这里已经阅读了几个关于SingleInstance的问题,但仍然找不到一个对我有帮助的直接答案。也就是说,如果我错过了什么,我道歉

我的问题是:

我正在为iOS和Android构建一个Xamarin表单应用程序。我在PCL中有一个单一的AppInitializer类,在这里我使用Autofac注册所有接口依赖项。然后,我将构建器中的容器指定为app类的静态属性。我遇到的问题是,当我使用.SingleInstance()注册所有内容时,实际上并没有得到一个实例

初始化逻辑示例:

var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
public ProfilePage()
{
     InitializeComponent();
     var displayModel = Model.CurrentMember;
     …
 }
 …
 **public IMemberViewModel Model =>
 AppContainer.Current.Resolve<IMemberViewModel>();**
然后,我在页面上使用上述模型,如下所示:

 public class MemberViewModel : ViewModelBase, IMemberViewModel
 {
  … 
  (see constructor above)
  …
  public MemberDisplay CurrentMember =>
        m_CurrentMember ?? (m_CurrentMember = new MemberDisplay())
页面使用示例:

var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
public ProfilePage()
{
     InitializeComponent();
     var displayModel = Model.CurrentMember;
     …
 }
 …
 **public IMemberViewModel Model =>
 AppContainer.Current.Resolve<IMemberViewModel>();**
在IMemberViewModel的实现中,我有一个方法可以设置CurrentMember的各种属性

操作顺序如下:

最终用户点击成员的图像。这将在IMemberViewModel实现的(理论上)单例实例上触发一个命令。此命令执行一个异步任务,等待对API的异步调用来加载该成员的数据。加载数据并在CurrentMember上设置属性后,应用程序将导航到配置文件屏幕。配置文件屏幕解析IMemberViewModel(如上所述)

预期行为: IMemberViewModel解析实例中CurrentMember的属性设置为刚从load data方法中设置的值。这一期望源于假设存在IMemberViewModel的单个实例

实际行为: CurrentMember的属性是默认值,即string.Empty、0、null等


奇怪的是,这并不是发生在每一款车型上。我有一个消息模型,我正在以相同的方式在同一屏幕上解析它,它似乎很好。

这个问题原来是由我们初始化所有内容的方式引起的。为子孙后代着想,我将简要介绍正在发生的事情以及我为防止这种情况所做的工作

以前的应用程序流:

var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
public ProfilePage()
{
     InitializeComponent();
     var displayModel = Model.CurrentMember;
     …
 }
 …
 **public IMemberViewModel Model =>
 AppContainer.Current.Resolve<IMemberViewModel>();**
  • 应用程序打开&调用构造函数。这将调用上面的初始化例程
  • 用户登录
  • IMemberViewModel的第一个实例使用静态容器解析
  • 弹出一条消息,询问用户推送通知权限
  • 发生这种情况时,将调用睡眠应用程序(iOS)
  • 用户选择答案后,调用OnResume
  • OnResume调用初始化例程
  • 已创建新的容器
  • 加载数据的调用发生在旧容器上,新页面引用新容器
  • 问题如上所述
流量修正:

var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
public ProfilePage()
{
     InitializeComponent();
     var displayModel = Model.CurrentMember;
     …
 }
 …
 **public IMemberViewModel Model =>
 AppContainer.Current.Resolve<IMemberViewModel>();**
首先,据我所知,如果在应用程序构造函数中进行初始化调用,则不需要在resume和/或start时进行初始化调用。如果该应用程序因其他应用程序需要内存空间而被“杀死”,则将在下次启动时创建该应用程序的新版本(请参阅和)

其次,因为我有妄想症,而且这不会有什么坏处,所以在appinit例程中,我现在检查容器是否存在,以及接口是否已经注册

public static void Init(ISetup setup)
{
    if (Container != null && IsModelRegistered()) return;

    RegisterDependencies(setup);
    …
}

private static bool IsModelRegistered()
{
    return Container.IsRegistered<IMemberViewModel>();
}
publicstaticvoidinit(ISetup设置)
{
if(Container!=null&&IsModelRegistered())返回;
注册依赖性(设置);
…
}
私有静态bool IsModelRegistered()
{
返回容器。IsRegistered();
}

这个问题原来是由我们初始化所有内容的方式引起的。为子孙后代着想,我将简要介绍正在发生的事情以及我为防止这种情况所做的工作

以前的应用程序流:

var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
public ProfilePage()
{
     InitializeComponent();
     var displayModel = Model.CurrentMember;
     …
 }
 …
 **public IMemberViewModel Model =>
 AppContainer.Current.Resolve<IMemberViewModel>();**
  • 应用程序打开&调用构造函数。这将调用上面的初始化例程
  • 用户登录
  • IMemberViewModel的第一个实例使用静态容器解析
  • 弹出一条消息,询问用户推送通知权限
  • 发生这种情况时,将调用睡眠应用程序(iOS)
  • 用户选择答案后,调用OnResume
  • OnResume调用初始化例程
  • 已创建新的容器
  • 加载数据的调用发生在旧容器上,新页面引用新容器
  • 问题如上所述
流量修正:

var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
public ProfilePage()
{
     InitializeComponent();
     var displayModel = Model.CurrentMember;
     …
 }
 …
 **public IMemberViewModel Model =>
 AppContainer.Current.Resolve<IMemberViewModel>();**
首先,据我所知,如果在应用程序构造函数中进行初始化调用,则不需要在resume和/或start时进行初始化调用。如果该应用程序因其他应用程序需要内存空间而被“杀死”,则将在下次启动时创建该应用程序的新版本(请参阅和)

其次,因为我有妄想症,而且这不会有什么坏处,所以在appinit例程中,我现在检查容器是否存在,以及接口是否已经注册

public static void Init(ISetup setup)
{
    if (Container != null && IsModelRegistered()) return;

    RegisterDependencies(setup);
    …
}

private static bool IsModelRegistered()
{
    return Container.IsRegistered<IMemberViewModel>();
}
publicstaticvoidinit(ISetup设置)
{
if(Container!=null&&IsModelRegistered())返回;
注册依赖性(设置);
…
}
私有静态bool IsModelRegistered()
{
返回容器。IsRegistered();
}

当您说您在到达页面之前设置了
Model.CurrentMember
的属性时,您的意思是您从同一个容器解析了
IMemberViewModel
并设置了属性吗?模型上的CurrentMember是一个可观察的对象,上面有一些字符串属性。我直接从IMemberViewModel实现中的加载数据调用中设置这些字符串(如name)。我的期望是,当我解析IMemberViewModel时,我会得到实现的单个实例。相反,我得到了该实现的一个新实例。我会更详细地更新我的问题。@Mickaëlderrie。我忘了在回复中标记您。在您使用
IMemberViewModel
的所有地方,您是否绝对确定已解决此问题