I've tried with
public string GetContentProperty(Type type)
{
var contentPropertyAttribute = type.GetTypeInfo().GetCustomAttribute<ContentPropertyAttribute>();
return contentPropertyAttribute?.Name;
}
But it always returns null.
In WPF it works OK.
I have been looking at this for longer than I really should have, and still don't know the complete answer. I sincerely hope someone else comes along and provides a better option.
What I've found so far is that on UWP, the call to GetCustomAttributes()
returns an empty enumeration. At first I thought this might have something to do with the type-stripping done for UWP assemblies, but I can reproduce the issue in a Debug build, without the "Compile with .NET Native tool chain" option enabled, so the compiled assembly should include complete type information. And even if I modify the Default.rd.xml
file to include <Type Name="Windows.UI.Xaml.Markup.ContentPropertyAttribute" Dynamic="Required All"/>
(on the theory that maybe the ContentPropertyAttribute
type was being omitted), that doesn't help.
So, I'm at a loss as to what exactly is going on. However, in the meantime, here is a version of your method that will work:
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();
}
(Rather than pass the Type
object in, I just made it generic and let the method do the work of finding the type.)
In the above, I convert the CustomAttributeNamedArgument
value type to a nullable type so I can use the FirstOrDefault()
, which I find more convenient than having to materialize the enumeration, inspecting its length, and then retrieving the first element if it's non-empty.
The fact that this works even while the GetCustomAttributes()
method does not still makes me think that this is somehow related to something that a compiled UWP assembly does that discards type information. But unfortunately, I don't know enough about that specific area of UWP to say how.
I would be the first to agree that the above is not a terribly great option. Having to get the declaration information for the attribute rather than the attribute itself, then searching for the property name in that data, and finally having to cast the untyped value property from the data back to string
so it can be returned, that's all very messy and not ideal.
But it does work. So, there's that. :)