Xamarin Forms/Prism/Shiny中DryIoc服务注册ContainerException异常排查
iOS平台DryIoc无法解析IInitService异常排查
启动iOS应用时抛出DryIoc容器异常,提示无法解析IInitService服务:
DryIoc.ContainerException: code: Error.UnableToResolveUnknownService; message: Unable to resolve resolution root PS.Forms.VoiceApp.Base.Interfaces.IInitService from container with scope {Name=null} with Rules with {TrackingDisposableTransients, UseDynamicRegistrationsAsFallbackOnly, FuncAndLazyWithoutRegistration, SelectLastRegisteredFactory} and without {ThrowOnRegisteringDisposableTransient, UseFastExpressionCompilerIfPlatformSupported} with FactorySelector=SelectLastRegisteredFactory with Made={FactoryMethod=ConstructorWithResolvableArguments} Where no service registrations found and no dynamic registrations found in 1 of Rules.DynamicServiceProviders and nothing found in 0 of Rules.UnknownServiceResolvers at DryIoc.Throw.It (System.Int32 error, System.Object arg0, System.Object arg1, System.Object arg2, System.Object arg3) [0x00000] in /_/src/DryIoc/Container.cs:13642 at DryIoc.Container.TryThrowUnableToResolve (DryIoc.Request request) [0x0006d] in /_/src/DryIoc/Container.cs:1088 at DryIoc.Container.DryIoc.IContainer.ResolveFactory (DryIoc.Request request) [0x00072] in /_/src/DryIoc/Container.cs:1068 at DryIoc.Container.ResolveAndCache (System.Int32 serviceTypeHash, System.Type serviceType, DryIoc.IfUnresolved ifUnresolved) [0x00021] in /_/src/DryIoc/Container.cs:367 at DryIoc.Container.DryIoc.IResolver.Resolve (System.Type serviceType, DryIoc.IfUnresolved ifUnresolved) [0x0011c] in /_/src/DryIoc/Container.cs:356 at DryIoc.Container.DryIoc.IResolver.Resolve (System.Type serviceType, System.Object serviceKey, DryIoc.IfUnresolved ifUnresolved, System.Type requiredServiceType, DryIoc.Request preResolveParent, System.Object[] args) [0x00039] in /_/src/DryIoc/Container.cs:428 at DryIoc.Resolver.Resolve (DryIoc.IResolver resolver, System.Type serviceType, System.Object[] args, DryIoc.IfUnresolved ifUnresolved, System.Type requiredServiceType, System.Object serviceKey) [0x00000] in /_/src/DryIoc/Container.cs:8087 at Prism.DryIoc.DryIocContainerExtension.Resolve (System.Type type, System.ValueTuple`2[System.Type,System.Object][] parameters) [0x0001c] in /_/src/Containers/Prism.DryIoc.Shared/DryIocContainerExtension.cs:294
我在AppDelegate.cs中注册了IInitService的iOS实现IOSInitService:
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) { this.PreventLinkerFromStrippingCommonLocalizationReferences(); Rg.Plugins.Popup.Popup.Init(); this.ShinyFinishedLaunching(new VoiceAppStartup { RegisterPlatformServices = services => { services.AddSingleton<IInitService, IOSInitService>(); } }); global::Xamarin.Forms.Forms.Init(); FormsControls.Touch.Main.Init(); this.LoadApplication(new App()); return base.FinishedLaunching(application, launchOptions); }
同时在App.xaml.cs中注册了其他跨平台服务(运行正常):
protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterPopupNavigationService(); containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>(); containerRegistry.RegisterSingleton<IShare, ShareImplementation>(); ...}
请问异常原因是什么?是否遗漏了某些步骤?
可能的原因与解决方法
服务注册容器不匹配
你通过Shiny的RegisterPlatformServices注册的服务,并未进入Prism使用的DryIoc容器实例。Prism的容器是在new App()初始化时创建的,Shiny的注册逻辑独立于Prism容器,导致服务无法被Prism容器识别。
解决方式:使用Prism的平台特定初始化机制:- 在iOS项目中实现
IPlatformInitializer接口:using Prism.Ioc; public class iOSPlatformInitializer : IPlatformInitializer { public void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterSingleton<IInitService, IOSInitService>(); } } - 修改
App.xaml.cs的构造函数,接收平台初始化器:public App(IPlatformInitializer initializer) : base(initializer) { } - 在
AppDelegate.cs中调整LoadApplication的调用:this.LoadApplication(new App(new iOSPlatformInitializer()));
- 在iOS项目中实现
iOS链接器剥离了实现类
iOS的链接器会移除未被直接引用的代码,如果IOSInitService没有被代码直接实例化,链接器可能会将其从编译包中移除,导致容器找不到实现。
解决方式:- 给
IOSInitService添加[Preserve]特性:using Xamarin.Forms; [Preserve(AllMembers = true)] public class IOSInitService : IInitService { // 实现代码 } - 或者在iOS项目的
Linker.xml中添加保留规则:<assembly fullname="你的iOS项目名称"> <type fullname="你的命名空间.IOSInitService" preserve="all"/> </assembly>
- 给
注册时机错误
当前代码先执行Shiny初始化,再加载App,Prism容器可能在Shiny注册时还未创建,导致服务未被正确注入。通过Prism的平台初始化器注册,可以确保服务在Prism容器初始化时被注册。接口与实现的引用/拼写问题
检查IInitService所在的程序集是否被iOS项目正确引用,IOSInitService是否正确实现了IInitService,确认接口名称、命名空间没有拼写错误。
内容的提问来源于stack exchange,提问作者user16291322
相关产品推荐
相关产品推荐

