.NET MAUI如何获取内部类TabbedPageManager的私有BottomNavigationView属性?
.NET MAUI中解决TabbedPage内部类私有属性访问的AOT警告问题
问题背景
在.NET MAUI应用中自定义TabbedPage行为时,通过反射访问内部类TabbedPageManager的私有属性BottomNavigationView触发了IL2075警告。原实现代码如下:
Microsoft.Maui.Handlers.TabbedViewHandler.Mapper.AppendToMapping("TabbedPageCenterLabels", (handler, view) => { var tabbedPageManager = typeof(TabbedPage).GetField("_tabbedPageManager", BindingFlags.NonPublic | BindingFlags.Instance)?. GetValue(handler.VirtualView); var navView = (BottomNavigationView?)tabbedPageManager.GetType() .GetProperty("BottomNavigationView", BindingFlags.NonPublic | BindingFlags.Instance) ?.GetValue(tabbedPageManager); });
由于TabbedPageManager是内部类,无法直接通过typeof(TabbedPageManager)获取类型;尝试使用UnsafeAccessor时,因参数类型不可访问而失败:
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_BottomNavigationView")] extern static BottomNavigationView InstanceGetter(TabbedPageManager @this);
解决方案
方案1:用UnsafeAccessor针对object类型访问私有属性
将UnsafeAccessor的参数类型改为object(规避内部类不可访问的限制),直接指定属性的Getter操作:
// 定义访问BottomNavigationView属性的Unsafe访问器 [UnsafeAccessor(UnsafeAccessorKind.PropertyGet, Name = "BottomNavigationView")] extern static BottomNavigationView? GetBottomNavigationView(object tabbedPageManager); // 在映射逻辑中使用 Microsoft.Maui.Handlers.TabbedViewHandler.Mapper.AppendToMapping("TabbedPageCenterLabels", (handler, view) => { // 获取_tabbedPageManager私有字段 var tabbedPageManagerField = typeof(TabbedPage).GetField("_tabbedPageManager", BindingFlags.NonPublic | BindingFlags.Instance); if (tabbedPageManagerField == null) return; var tabbedPageManager = tabbedPageManagerField.GetValue(handler.VirtualView); if (tabbedPageManager == null) return; // 通过UnsafeAccessor获取目标属性 var navView = GetBottomNavigationView(tabbedPageManager); // 后续对navView的自定义逻辑... });
方案2:全流程用UnsafeAccessor替代反射(彻底消除IL2075)
同时为_tabbedPageManager字段和BottomNavigationView属性定义UnsafeAccessor,完全避免反射操作:
// 访问TabbedPage的_tabbedPageManager私有字段 [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_tabbedPageManager")] extern static object? GetTabbedPageManager(TabbedPage tabbedPage); // 访问TabbedPageManager的BottomNavigationView私有属性 [UnsafeAccessor(UnsafeAccessorKind.PropertyGet, Name = "BottomNavigationView")] extern static BottomNavigationView? GetBottomNavigationView(object tabbedPageManager); // 在映射逻辑中使用 Microsoft.Maui.Handlers.TabbedViewHandler.Mapper.AppendToMapping("TabbedPageCenterLabels", (handler, view) => { if (handler.VirtualView is not TabbedPage tabbedPage) return; var tabbedPageManager = GetTabbedPageManager(tabbedPage); if (tabbedPageManager == null) return; var navView = GetBottomNavigationView(tabbedPageManager); // 后续对navView的自定义逻辑... });
注意事项
UnsafeAccessor需要.NET 7及以上版本支持,且需在项目csproj文件中启用不安全代码:<AllowUnsafeBlocks>true</AllowUnsafeBlocks>。- 该方式依赖.NET MAUI内部实现细节,版本更新可能导致内部结构变化,需做好兼容性测试。
- 相比反射,
UnsafeAccessor在AOT编译下无警告,且性能更优。
内容的提问来源于stack exchange,提问作者Saftpresse99
相关产品推荐
相关产品推荐

