[Proposal] Remove `BindableObject` Constraint from `.Assign()` and `.Invoke()`
brminnick opened this issue · 5 comments
Remove Constraints from Assign()
and Invoke()
- Proposed
- Prototype
- Implementation
- iOS Support
- Android Support
- macOS Support
- Windows Support
- Unit Tests
- Sample
- Documentation: MicrosoftDocs/CommunityToolkit#161
Summary
This Proposal removes the BindableObject
constraint (where T : BindableObject
) from .Assign()
and .Invoke()
extension methods.
Before
public static TBindable Assign<TBindable, TVariable>(this TBindable bindable, out TVariable variable)
where TBindable : BindableObject, TVariable;
public static TBindable Invoke<TBindable>(this TBindable bindable, Action<TBindable> action)
where TBindable : BindableObject;
After
public static TAssignable Assign<TAssignable, TVariable>(this TAssignable assignable, out TVariable variable)
where TAssignable : TVariable;
public static TAssignable Invoke<TAssignable>(this TAssignable assignable, Action<TAssignable> action);
// no constraint
Motivation
There is nothing in Assign()
or Invoke()
that requires generic, T
, to be a BindableObject
.
Removing the constraint (eg removing where T : Bindable
), allows the .Assign()
and .Invoke()
extension methods to be used on any type.
This is especially useful for custom controls that may implement BindableObject
.
Detailed Design
I recommend creating a new class, public static class Object Extensions
.
Both .Assign()
and .Invoke()
are currently in BindableObjectExtensions.cs
. Keeping them in BindableObjectExtensions.cs
doesn't make much sense now that they are no longer constrained to BindableObject
.
namespace CommunityToolkit.Maui.Markup;
/// <summary>
/// Extension Methods for Unconstrained Objects
/// </summary>
public static class ObjectExtensions
{
/// <summary>
/// Assign <typeparam name="TAssignable"> to a variable
/// </summary>
/// <typeparam name="TAssignable"></typeparam>
/// <typeparam name="TVariable"></typeparam>
/// <param name="assignable"></param>
/// <param name="variable"></param>
/// <returns>TBindable</returns>
public static TAssignable Assign<TAssignable, TVariable>(this TAssignable assignable, out TVariable variable)
where TAssignable : TVariable
{
variable = assignable;
return assignable;
}
/// <summary>
/// Perform an action on <typeparam name="TAssignable">
/// </summary>
/// <typeparam name="TAssignable"></typeparam>
/// <param name="assignable"></param>
/// <param name="action"></param>
/// <returns>TBindable</returns>
public static TAssignable Invoke<TAssignable>(this TAssignable assignable, Action<TAssignable> action)
{
ArgumentNullException.ThrowIfNull(action);
action.Invoke(assignable);
return assignable;
}
}
Usage Syntax
C# Usage
class SamplePage : ContentPage
{
readonly Label _label;
readonly string _title;
public SamplePage()
{
Title = "Sample Page".Assign(out _title);
Content = new Button().Invoke(button => button.Clicked += HandleButtonClicked);
}
}
Drawbacks
None. This is not a breaking change.
Alternatives
We could create two new extension methods, but since it is not a breaking change to remove constraints, I recommend we move forward with keeping the existing extension methods and removing their constraints.
Unresolved Questions
None
I approve this feature ✅
Approve!
Gets my vote
I too approve ✅
Reopening Proposal.
Only Proposals moved to the Closed
Project Column and Completed
Project Column can be closed.