使用DependencyServiceWrapper时Xamarin DependencyService Get()返回NULL
这种问题我之前也碰到过几次,咱们一步步拆解可能的原因和解决办法:
1. 先检查Wrapper的Get()方法实现是否正确
最常见的坑是Wrapper里的Get方法没正确转发泛型请求,比如不小心硬编码了特定类型:
// ❌ 错误写法:固定返回IConnectivityService,其他类型都会转成null public T Get<T>() where T : class { return DependencyService.Get<IConnectivityService>() as T; }
要改成正确的泛型转发:
// ✅ 正确写法:传递泛型参数给原生DependencyService public T Get<T>() where T : class { return DependencyService.Get<T>(); }
2. 排查Wrapper是否有错误的缓存逻辑
如果Wrapper里做了服务缓存(比如用字典存已获取的服务),可能在ITaskRepository还没注册时就尝试获取,导致null被缓存下来:
// ❌ 有问题的缓存逻辑 private Dictionary<Type, object> _cachedServices = new(); public T Get<T>() where T : class { if (_cachedServices.ContainsKey(typeof(T))) return _cachedServices[typeof(T)] as T; var service = DependencyService.Get<T>(); _cachedServices.Add(typeof(T), service); // 第一次获取时未注册,存了null return service; }
解决办法:要么去掉缓存逻辑(单元测试场景下其实没必要缓存),要么在服务注册完成后清空缓存,或者每次获取都跳过缓存直接调用原生DependencyService.Get<T>()。
3. 确认类型的命名空间和引用一致性
有可能你在Wrapper里引用的ITaskRepository和注册的不是同一个类型——比如同名但不同命名空间的接口。右键点击两处的ITaskRepository,选择「查看定义」,确认完全一致的命名空间和类型签名。
4. 检查单元测试中的服务模拟注册逻辑
你提到这个Wrapper是为单元测试替换依赖用的,那要确认测试代码里是否给Wrapper注册了ITaskRepository的模拟实现:
// 示例:测试中给Wrapper注入模拟服务 DependencyServiceWrapper.SetTestProvider(new MockServiceProvider() .AddMock<IConnectivityService>(new Mock<IConnectivityService>().Object) .AddMock<ITaskRepository>(new Mock<ITaskRepository>().Object) // 别漏了这行! );
如果测试时只注册了IConnectivityService,没加ITaskRepository的模拟,Wrapper就会返回null;而直接调用原生DependencyService.Get<T>()可能走了平台侧的注册,所以能拿到实例。
5. 验证服务注册时机
确认ITaskRepository的注册代码(比如DependencyService.Register<ITaskRepository, TaskRepository>())是在ViewModel构造、Wrapper调用之前执行的。比如平台项目的App.xaml.cs的OnInitialized或OnStart方法里,要确保注册逻辑优先于ViewModel的初始化。
内容的提问来源于stack exchange,提问作者David Hawkins

