.NET MAUI中IRootObjectProvider与IProvideValueTarget服务注入问题求助
.NET MAUI 获取IRootObjectProvider与IProvideValueTarget的解决方法
核心原因
IRootObjectProvider和IProvideValueTarget是XAML解析器处理标记扩展(MarkupExtension)时临时注入的上下文服务,不会注册到全局DI容器(MauiContext.Services),对应的实现类XamlValueTargetProvider、XamlRootObjectProvider是内部类,无法直接引用。
可行解决方案
1. 利用标记扩展生命周期获取(推荐)
官方设计中,这两个服务仅在IMarkupExtension<T>.ProvideValue(IServiceProvider)方法的调用上下文内可用。如果你的验证逻辑和绑定相关,直接将验证逻辑封装为标记扩展:
public class ValidationExtension : IMarkupExtension<BindingBase> { public BindingBase ProvideValue(IServiceProvider serviceProvider) { // 直接从方法参数的serviceProvider中获取服务 var rootProvider = serviceProvider.GetRequiredService<IRootObjectProvider>(); var targetProvider = serviceProvider.GetRequiredService<IProvideValueTarget>(); var root = rootProvider.RootObject as BindableObject; var targetObject = targetProvider.TargetObject as BindableObject; // 执行你的验证逻辑 // ... // 返回绑定对象(根据需求调整) return new Binding(nameof(YourViewModel.Property)) { ValidatesOnNotifyDataErrors = true, // 其他绑定配置 }; } }
在XAML中直接使用该扩展:
<Entry Text="{local:ValidationExtension}" />
2. 自定义接口实现(特殊场景用)
如果必须在Handler等非标记扩展场景中获取,需要自己实现这两个接口,手动注入上下文信息:
先实现自定义服务类:
// 自定义IRootObjectProvider实现 public class CustomRootObjectProvider : IRootObjectProvider { public object RootObject { get; } public CustomRootObjectProvider(BindableObject root) { RootObject = root; } } // 自定义IProvideValueTarget实现 public class CustomValueTargetProvider : IProvideValueTarget { public object TargetObject { get; } public object TargetProperty { get; } public CustomValueTargetProvider(BindableObject targetObject, BindableProperty targetProperty) { TargetObject = targetObject; TargetProperty = targetProperty; } }
然后在需要的地方手动创建实例(或注册到局部DI容器):
// 假设已获取到当前根对象(如页面)和目标控件/属性 var currentPage = this as ContentPage; var targetEntry = this.FindByName<Entry>("MyEntry"); // 创建自定义服务实例 var rootProvider = new CustomRootObjectProvider(currentPage); var targetProvider = new CustomValueTargetProvider(targetEntry, Entry.TextProperty); // 直接使用实例,或注册到局部ServiceProvider var localServices = new ServiceCollection(); localServices.AddSingleton<IRootObjectProvider>(rootProvider); localServices.AddSingleton<IProvideValueTarget>(targetProvider); var localProvider = localServices.BuildServiceProvider(); // 后续通过localProvider获取服务
内容的提问来源于stack exchange,提问作者Wasyster
相关产品推荐
相关产品推荐

