#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. Я надеюсь, что кто-нибудь может дать нам лучшее понимание этого странного поведения. Спасибо, Питер!