Prism 7 + Xamarin.Forms:DI容器注册与解析问题咨询
嘿,我来帮你理清楚这两个Prism 7 DI相关的问题,我自己在项目里也用过这套框架,所以挺熟悉的:
首先得说,Prism的设计理念其实更推荐你在启动阶段的RegisterTypes方法里完成所有依赖注册,这样既清晰又符合DI的最佳实践。但如果确实有场景需要在运行时(比如其他页面、ViewModel里)注册服务,除了保存IContainerRegistry实例复用,还有这两种可行的方式:
- 通过
IContainerProvider获取底层容器:你可以在ViewModel或者页面的构造函数中注入IContainerProvider,然后调用它的GetContainer()方法拿到你正在使用的具体容器实例(比如Unity、DryIoc或Autofac的容器对象),接着用对应容器的原生API来完成注册。举个DryIoc的例子:
public MyPageViewModel(IContainerProvider containerProvider) { var container = containerProvider.GetContainer(); // 注册ITextService为TextService的单例 container.Register<ITextService, TextService>(Reuse.Singleton); }
注意:不同容器的注册语法会略有差异,你需要根据自己使用的容器来调整代码。
- 直接注入
IContainerExtension:IContainerRegistry和IContainerProvider其实都是IContainerExtension的子集,你也可以直接注入IContainerExtension<TContainer>(TContainer是你用的容器类型),这样能直接操作容器,但这种方式的耦合性会稍高一些。
另外要提醒的是,运行时注册可能会带来线程安全问题,而且如果注册的服务已经被解析过,部分容器可能不会更新注册逻辑,所以如果能在启动阶段完成注册,尽量还是优先这么做。
你看到的两种写法其实是Prism提供的两种单例注册方式,对应不同的使用场景:
ContainerRegistry.RegisterInstance<ITextService>(new TextService());:这种是注册已实例化的对象作为单例。你自己提前创建好TextService的实例,然后告诉容器:“以后任何地方请求ITextService,都返回这个已经创建好的实例”。这种方式适合你需要提前初始化实例(比如要传入配置参数),或者已经有现成的对象要作为单例使用的场景。containerRegistry.RegisterSingleton<ILoggerFacade, EmptyLogger>();:这种是注册类型映射的单例。你不需要提前创建实例,而是告诉容器:“当第一次有人请求ILoggerFacade时,创建一个EmptyLogger的实例,并且之后所有请求都复用这个实例”。容器会负责实例的创建(包括自动注入它的依赖)和生命周期管理,属于延迟初始化的单例。
简单来说,前者是“给容器一个现成的单例对象”,后者是“告诉容器怎么创建单例,需要的时候再创建”。两种方式都能实现单例效果,选哪种取决于你是否需要提前初始化实例。
内容的提问来源于stack exchange,提问作者TheDeveloper

