Skip to content

[Feature] Support enumerable/collection interfaces for bindable parameters/EventCallback<T> #12593

@bzd3y

Description

@bzd3y

Currently Razor doesn't seem to support binding to a parameter that is a generic collection interface from something that implements that interface. It will produce an error along the lines of:

Argument 10: cannot convert from 'Microsoft.AspNetCore.Components.EventCallback<System.Collections.Generic.List>' to 'Microsoft.AspNetCore.Components.EventCallback<System.Collections.Generic.IEnumerable>'

Of course this issue isn't specific to collections (or interfaces), but they seem to be the area that would require the least amount of effort while also providing the most value.

Two things that come to mind:

  1. EventCallback<T> may need to be made covariant (or maybe I am reversing that)?
  2. Or, perhaps the code generator just needs to pay attention to the type of the parameter instead of the type of the object it is being bound to?

In both cases, the generated delegate would need to know to handle the "known" collections and their conversions, i.e. use methods like Enumerable.ToList() when necessary.

A simplified but contrived example:

@code
{
    List<string> strings = [ "a", "bunch", "of", "strings" ];
    HashSet<string> importantStrings = [];
}
@* FindImportantStrings.ImportantStrings is a [Parameter]IEnumerable<string>*@
<FindImportantStrings AllStrings="strings" @bind-ImportantStrings="importantStrings" />

This would generate an error like the one above, which forces components to be opinionated/lock down the types of collections the consuming developer uses or the author has to create a variant of the component for each type of collection they might want to support.

It's probably worth pointing out that AllStrings could also be an IEnumerable<string> and, as we would expect, there is no problem assigning a List<string> to it.

But it seems like all (easier said than done, I'm sure) that needs to happen is that the code generator could check the types involved and see if they are different and if they are, then generate code that:

  1. Calls the appropriate Enumerable conversation method.
  2. Or, ideally, just uses the spread operator and lets the compiler take care of calling the appropriate conversion method.

Possible problems: I suppose it is possible that there are some semantics with binding that require or expect the source and destination to be the same object and not copies, at least in the case of reference types. If that is the case, then maybe there could just be some way to opt in (or out?) to this, e.g. [Parameter(convertCollections = true)].

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions