Как я могу определить целевой тип для возвращаемого значения расширения разметки?

#c# #.net #wpf #xaml #markup-extensions

#c# #.net #wpf #xaml #разметка-расширения

Вопрос:

Я пишу пользовательское расширение разметки. В его ProvideValue методе я хотел бы изменить / преобразовать возвращаемое значение на основе предполагаемого целевого типа свойства, для которого используется расширение разметки для предоставления значения.

(В принципе, a TypeConverter знает о целевом типе окружающей его привязки и может соответствующим образом адаптировать свое поведение; я хотел бы сделать то же самое в моем расширении разметки.)

Теперь ProvideValue метод получает только IServiceProvider в качестве аргумента. Кажется, я должен быть в состоянии использовать его для получения объекта, который предоставляет мне желаемый бит контекстной информации, но пока ни одна из моих попыток сделать это не была полностью удовлетворительной:

  • Я извлек IDestinationTypeProvider реализацию. Хотя кажется, что он делает именно то, что мне нужно, основываясь на его имени, к сожалению, он выдает исключение:

     var dtp = (IDestinationTypeProvider)serviceProvider.GetService(typeof(IDestinationTypeProvider));
    var destType = dtp.GetDestinationType(); // NullReferenceException on this line
      
  • Я извлек IProvideValueTarget реализацию. Он предоставляет мне целевое свойство, но только как System.Object , так что, похоже, я должен сам подготовить свой код для обработки различных (?) типов свойств и получения типа самостоятельно.

Каким предполагаемым способом расширение разметки может получить свой целевой тип?

Ответ №1:

Используйте IServiceProvider , чтобы получить IProvideValueTarget , затем посмотрите на TargetProperty , который должен (но не гарантировано) быть DependencyProperty .

 var provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
var propertyType = (provideValueTarget.TargetProperty as DependencyProperty)?.PropertyType;
// Test propertyType for null
  

Целевым свойством также может быть an, EventInfo если MarkupExtension используется с событием, или a MethodInfo если оно используется с присоединенным событием (или, как вы указали в комментариях, a PropertyInfo если оно используется с обычным свойством).

К сожалению, я думаю, что это единственный способ сделать это. DynamicResourceExtension имеет аналогичные проверки, смотрите здесь и здесь — если бы был лучший API, я предполагаю, что он использовал бы его.

Комментарии:

1. Или PropertyInfo если расширение разметки используется в обычном свойстве (не зависящем). Или что-то совершенно другое в будущей версии фреймворка. Я надеялся, что BCL избавит меня от этого, но если это действительно единственный способ, я собираюсь принять этот ответ немного позже.

2. @O.R.Mapper Я почти уверен, что это единственный способ сделать это, к сожалению. Я добавил ссылку на некоторый код WPF, который выполняет те же проверки. Если вам удастся найти лучший способ, я буду рад!