Xamarin在运行时检测HttpClient Stack

3
在 Xamarin iOS 应用程序中,我能够在运行时指定要使用的 HttpClient 实现:

https://developer.xamarin.com/guides/cross-platform/macios/http-stack/

然而,这个设置只影响使用默认构造函数构建的 HttpClients:
var client = new HttpClient()

但是如果我想通过向构造函数提供自定义的DelegatingHandler来为我的http客户端添加一些请求拦截,该怎么办?那么我将使用另一个构造函数:

var myDel = new MyDel(RUNTIME_HANDLER_GOES_HERE);
var client = new HttpClient(myDel);

理想情况下,在运行时我需要知道在编译时项目设置中选择了哪个httpHandler,以便在运行时将其包装在myDel中。我该怎么做?
更新:我能够找到负责在mono源代码中选择适当处理程序的代码:https://github.com/mono/mono/blob/master/mcs/class/System.Net.Http/HttpClientEx.cs#L28 但是RuntimeOptions类是内部类,我只能在运行时通过反射使用它。 在这种情况下,Xamarin的链接器会从发布模式的dll中剥离RuntimeOptions,导致应用程序在发布和adhoc构建中崩溃,但在调试中不会。 有人知道在启用链接器的Xamarin构建中会发生什么事情,以便我能够利用它来查找运行时httphandler吗?

如果可能的话,我会注册Xamarin大学的免费试用,并且有一个关于这个主题的课程,可能会很有帮助。它的课程编号是XAM150 REST Web Services,它比我讲得更好。从我记得的那门课程中,你可以在代码中设置httpClienthandlers,而不是使用项目设置,并根据你想要使用的DelegatingHandlers在CFNetworkHandler和NSUrlSessionHander之间进行切换。由于你是在代码中执行此操作,因此你知道在运行时安装到你的HttpClient的HTTPClientHandler是哪一个。 - Bearcat9425
@Bearcat9425,是的,现在我觉得你说得对。我当然可以控制将哪些处理程序作为innerHandler传递到我的DelegatingHandler中,但我想知道是否有能力确定在Xamarin的项目设置中选择哪个处理程序作为默认值,以尝试使其在整个解决方案中保持一致,并通过Autofac注入所选的处理程序到我的服务的HttpClient。 - FreoN
我看到了那个注释,但我不确定。 - Bearcat9425
1个回答

2
不要与链接器对抗 - 它之所以删除它,是因为这是一种大小优化,可以只使用所需的处理程序。
但是您仍然可以在其他地方使用反射,这是链接器无法删除的地方。您可以在我们的HttpClient示例中看到这样的示例。下面是重要的一行:
typeof(HttpMessageInvoker).GetField("_handler", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue (client).GetType ();

坦白地说,当你使用链接器时,反射也不安全,因为链接器不知道你是否会在编译时使用某些私有/公共API,因为成员名称是硬编码的。然而,你的答案是最好的。当我不知道HttpClient的内部构造方式时,我可以实例化HttpClient并反射它(在这种情况下,链接器没有剥离任何内容,因为我实际上在我的代码中使用了HttpClient),以便获取内部处理程序。不太干净,但可行,是的。 - FreoN
2
处理程序遗憾地未在公共API中公开(例如作为属性)。但是,反射可以安全地避免链接器,您只需要确保信息无法被删除(由您的代码或调用的代码)。在这种情况下,如果您正在使用HttpClient,则无法删除“handler”。当然,它本身并不比反射更安全,因为它基于可能随时间而变化的内部机制(但这与链接器本身无关)。 - poupou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接