Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ICustomPropertyProvider AOT safe #1677

Merged
merged 12 commits into from
Jul 23, 2024

Conversation

manodasanW
Copy link
Member

  • Added BindableCustomPropertyAttribute to allow to specify that public properties from the class are bindable. Either all public properties can be bindable by passing no arguments to the constructor. Or the names of the properties and the types of the indexer types can be passed to specify which ones to make bindable.
  • By adding this attribute to a class and marking it partial, an interface Microsoft.UI.Xaml.Data.IBindableCustomPropertyImplementation gets implemented on that class via the source generator which provides the implementation to support ICustomPropertyProvider. This is done as an interface instead of an attribute because this allows to support generic types while the attribute model won't work with it. In addition, we only need to worry about supporting classes and not other types.
  • Added a bunch of tests to validate
  • This model doesn't support built-in .NET types but those can be worked around by wrapping it around a class or so. Support for that can be added via other means if needed in the future.
partial class Language : global::Microsoft.UI.Xaml.Data.IBindableCustomPropertyImplementation
{
    global::Microsoft.UI.Xaml.Data.BindableCustomProperty global::Microsoft.UI.Xaml.Data.IBindableCustomPropertyImplementation.GetProperty(string name)
    {
        if (name == "Name")
        {
            return new global::Microsoft.UI.Xaml.Data.BindableCustomProperty(
                true,
                false,
                "Name",
                typeof(string),
                static (instance) => ((Language)instance).Name,
                null,
                null,
                null);
        }
        if (name == "Value")
        {
            return new global::Microsoft.UI.Xaml.Data.BindableCustomProperty(
                true,
                true,
                "Value",
                typeof(int),
                static (instance) => ((Language)instance).Value,
                static (instance, value) => ((Language)instance).Value = (int)value,
                null,
                null);
        }
        return default;
    }

    global::Microsoft.UI.Xaml.Data.BindableCustomProperty global::Microsoft.UI.Xaml.Data.IBindableCustomPropertyImplementation.GetProperty(global::System.Type indexParameterType)
    {
        if (indexParameterType == typeof(int))
        {
            return new global::Microsoft.UI.Xaml.Data.BindableCustomProperty(
                true,
                true,
                "Item",
                typeof(string),
                null,
                null,
                static (instance, index) => ((Language)instance)[(int)index],
                static (instance, value, index) => ((Language)instance)[(int)index] = (string)value);
        }
        return default;
    }
}

@manodasanW manodasanW requested a review from Scottj1s July 22, 2024 05:19
{
for (var curSymbol = symbol; curSymbol != null; curSymbol = curSymbol.BaseType)
{
foreach (var propertySymbol in curSymbol.GetMembers().
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: we should also make sure this works correctly with partial properties. We can handle this in a follow up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using symbol data to get this data, so I believe it should. But we can confirm after.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more worried about the fact you might see two different property symbols for the same member (one being the definition, one being the implementation part), and that the fact they'd be "duplicate" might cause problems.

src/WinRT.Runtime/Attributes.cs Show resolved Hide resolved
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException(
$"ICustomProperty support used by XAML binding for '{target.GetType()}' requires the type to marked with 'WinRT.BindableCustomPropertyAttribute'. " +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any plans to document this in greater detail, like with an md on the repo? Xaml Compiler could then point errors/warnings to that page.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can get our aot.md updated to mention this in a follow up PR.

WF::IInspectable const& bindableObject,
hstring property,
Windows::UI::Xaml::Interop::TypeName const& indexerType,
bool validateOnlyExists,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enums (or name:value syntax) would be easier to read at call sites

return true;
}

if (customProperty.Name() != property ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the purpose of passing these bools in? given they have to match customProperty, why not just use the latter? (they seem redundant)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is validating expected vs actual. I will have a follow up PR to address this along with your enum comment for easier readability.

@manodasanW manodasanW merged commit f8cb6a0 into staging/AOT Jul 23, 2024
2 of 9 checks passed
@manodasanW manodasanW deleted the manodasanw/custombindable2 branch July 23, 2024 01:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants