Как получить имя свойства содержимого в UWP?

#c# #.net #reflection #uwp

#c# #.net #отражение #uwp

Вопрос:

Я пробовал с

 public string GetContentProperty(Type type)
{
     var contentPropertyAttribute = type.GetTypeInfo().GetCustomAttribute<ContentPropertyAttribute>();
     return contentPropertyAttribute?.Name;
}
 

Но оно всегда возвращает null.

В WPF это работает нормально.

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

1. Я поместил это в заголовок 🙂 В любом случае, я удалю тег WPF, чтобы избежать путаницы

2. Попробуйте IntrospectionExtensions.GetTypeInfo(type).GetCustomAttribute<ContentPropertyAttribute>();

Ответ №1:

Я смотрел на это дольше, чем следовало бы, и до сих пор не знаю полного ответа. Я искренне надеюсь, что кто-нибудь другой придет и предложит лучший вариант.

До сих пор я обнаружил, что в UWP вызов GetCustomAttributes() возвращает пустое перечисление. Сначала я подумал, что это может иметь какое-то отношение к удалению типов, выполняемому для сборок UWP, но я могу воспроизвести проблему в отладочной сборке без «Compile with .Опция «NET Native tool chain» включена, поэтому скомпилированная сборка должна содержать полную информацию о типе. И даже если я изменю Default.rd.xml файл на include <Type Name="Windows.UI.Xaml.Markup.ContentPropertyAttribute" Dynamic="Required All"/> (исходя из теории, что, возможно ContentPropertyAttribute , тип был опущен), это не поможет.

Итак, я в недоумении относительно того, что именно происходит. Однако, в то же время, вот версия вашего метода, которая будет работать:

 static string GetContentProperty<TSource>()
{
    return typeof(TSource).GetTypeInfo().CustomAttributes
        .Where(a => a.AttributeType == typeof(ContentPropertyAttribute))
        .FirstOrDefault()?.NamedArguments.Cast<CustomAttributeNamedArgument?>()
        .Where(n => n.Value.MemberName == "Name")
        .FirstOrDefault()?.TypedValue.Value.ToString();
}
 

(Вместо того, чтобы передавать Type объект, я просто сделал его универсальным и позволил методу выполнять работу по поиску типа.)

В приведенном выше примере я преобразую CustomAttributeNamedArgument тип значения в тип с нулевым значением, чтобы я мог использовать FirstOrDefault() , что я нахожу более удобным, чем материализовать перечисление, проверять его длину, а затем извлекать первый элемент, если он непустой.

Тот факт, что это работает, даже если GetCustomAttributes() метод все еще не работает, заставляет меня думать, что это как-то связано с чем-то, что делает скомпилированная сборка UWP, которая отбрасывает информацию о типе. Но, к сожалению, я недостаточно знаю об этой конкретной области UWP, чтобы сказать, как это сделать.

Я был бы первым, кто согласился бы, что приведенное выше не очень хороший вариант. Необходимость получать информацию объявления для атрибута, а не сам атрибут, затем искать имя свойства в этих данных и, наконец, приводить свойство нетипизированного значения из данных обратно string , чтобы его можно было вернуть, все это очень запутанно и не идеально.

Но это работает. Итак, вот и все. 🙂

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

1. Я надеюсь, что кто-нибудь может дать нам лучшее понимание этого странного поведения. Спасибо, Питер!