Обнаружение стека Xamarin HttpClient во время выполнения

В приложении Xamarin iOS я могу указать, какую реализацию HttpClient использовать во время выполнения:

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

Однако этот параметр влияет только на HttpClients, созданные с использованием ctor по умолчанию:

var client = new HttpClient()

Но что, если я хочу добавить перехват запросов к моему http-клиенту, предоставив ctor собственный DelegatingHandler? Затем я буду использовать другой ctor:

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

В идеале во время выполнения мне нужно знать, какой httpHandler выбран в настройках проекта времени компиляции, чтобы myDel обернул его во время выполнения. Как это сделать?

UPD Мне удалось найти код, отвечающий за выбор подходящего обработчика в исходниках моно: https://github.com/mono/mono/blob/master/mcs/class/System.Net.Http/HttpClientEx.cs#L28 однако класс RuntimeOptions является внутренним, и я могу использовать его только через отражение во время выполнения. Однако в этом случае компоновщик Xamarin удаляет RuntimeOptions из dll в режиме выпуска, и приложение аварийно завершает работу в выпусках и специальных сборках, но не в отладке. Кто-нибудь знает, что происходит с RuntimeOptions в сборке xamarin с поддержкой компоновщика, поэтому я могу использовать его, чтобы узнать httphandler во время выполнения?


person FreoN    schedule 15.06.2016    source источник
comment
Если это вообще возможно, я бы подписался на бесплатную пробную версию в Университете Xamarin, и есть курс по этой самой теме, который может быть большим подспорьем. Его курс XAM150 REST Web Services, и он объясняет вещи намного лучше, чем я. Из того, что я помню из этого курса, вы можете установить httpClienthandlers в коде по сравнению с использованием настроек проекта и переключаться между CFNetworkHandler и NSUrlSessionHander по мере необходимости на основе ваших DelegatingHandlers, которые вы хотите использовать . Поскольку вы делаете это в коде, вы знаете во время выполнения, какой HTTPClientHandler вы устанавливаете на свой HttpClient.   -  person Bearcat9425    schedule 15.06.2016
comment
@ Bearcat9425 Да, теперь мне кажется, что ты прав. Конечно, я могу контролировать, какие обработчики передавать в мой DelegatingHandler как innerHandler, мне просто интересно, есть ли возможность определить, какой обработчик выбран по умолчанию в настройках проекта Xamarin, чтобы попытаться сделать его согласованным во всем решении и, например, внедрить это выбранный обработчик через Autofac или что-то еще в HttpClient моего сервиса.   -  person FreoN    schedule 15.06.2016
comment
Я вижу на этой ноте я не уверен.   -  person Bearcat9425    schedule 15.06.2016


Ответы (1)


Не боритесь с компоновщиком — он удаляет его, потому что это оптимизация размера, позволяющая просто использовать требуемый обработчик (обработчики).

Однако вы все равно можете использовать отражение в другом месте, которое компоновщик не может удалить. Вы можете увидеть такой пример в нашем примере HttpClient. Вот важная строка:

typeof(HttpMessageInvoker).GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue (client).GetType ();
person poupou    schedule 16.06.2016
comment
Ну, откровенно говоря, отражение тоже небезопасно, когда вы используете компоновщик, поскольку компоновщик не знает, собираетесь ли вы использовать определенные частные/общедоступные API во время компиляции, потому что имена членов жестко закодированы. Однако ваш ответ подходит лучше всего. Когда я не знаю, как внутренне устроено HttpClient под капотом, я могу создать экземпляр HttpClient и отразить (и в этом случае компоновщик ничего не удаляет, потому что я фактически использую HttpClient в своем коде), чтобы получить внутренний обработчик. Не чисто, но работает, да. - person FreoN; 16.06.2016
comment
К сожалению, обработчик не раскрывается (например, как свойство) общедоступным API. Однако отражение может быть безопасным для компоновщика, вам нужно только убедиться, что информация не может быть удалена (вашим кодом или кодом, который вы вызываете). В этом случае handler нельзя удалить, если вы используете HttpClient. Конечно, это не более безопасно, чем само отражение, поскольку оно основано на внутренних компонентах, которые могут меняться со временем (но это не связано с самим компоновщиком). - person poupou; 16.06.2016