Skip to content

Improve Blazor CascadingTypeParameter support - Current compiler cannot handle common scenarios. #10757

Open
@audacode

Description

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

I expected the CascadingTypeParameter feature to work in the most common and obvious scenarios, but it does not. If the cascaded type was a string, it should be possible to use <Widget Action="item => Console.WriteLine(item)" /> instead of <Widget Action="(string item) => Console.WriteLine(item)" />. If you were passing in a parameter, it should be possible to do this <Widget Item="Hello" /> instead of needing to do this <Widget Item="@("Hello")" />. The CascadingTypeParameter feature was intended to resolve this type of issue but needs more work.

Describe the solution you'd like

Imagine this repeater:

@attribute [CascadingTypeParameter(nameof(T))]
@typeparam T

@foreach (var item in Items)
{
    @ChildContent(item)
}
@code {
    [Parameter] public RenderFragment<T> ChildContent { get; set; }
    [Parameter] public IEnumerable<T> Items { get; set;}
}

Then this Widget component intended to be used inside the repeater:

@typeparam T
Type is @typeof(T)
@code {
    [Parameter] public EventCallback<T> Action { get; set; }
    [Parameter] public T? Item { get; set; }
}

Warning: Do not overthink this widget as it is not intended to do anything sensible, other than demonstrate compiler limitations.

Now imagine we use the component like such:

<Repeater Items="items">
    <Widget Action="(string i) => Console.WriteLine(i)" />
</Repeater>
@code {
List<string> items = ["David", "Fred", "Jimmy", "Banjo"];
}

The above code works, and <Widget T="string" Action="i => Console.WriteLine(i)" /> also works. However, it is completely reasonable to expect to be able to use the following syntax:

<Widget Action="i => Console.WriteLine(i)" />

Another example of the compiler's mediocre compilation process is the following example. Let us say we write this code:

<Widget Item=@("Hello") />

That works, but because T is a string, for consistency with the way the rest of blazor works, we would expect this to work (noting that it does work if the underlying type was a string instead of a type parameter, where the parameter was a string) :

<Widget Item="Hello" />

However, this does not work (it looks for a member called Hello, which is what blazor would normally do for anything other than a string. Even this does NOT work: <Widget T="string" Item="Hello" />.

@danroth27 and @SteveSandersonMS I had thought we were further along than this once we got to .NET 6 and added the CascadingTypeParameter feature. It is hard, not being on the compiler team, to understand why when an outer component uses CascadingTypeParameter, that that isn't the same as directly passing in the type using the old-school T="string" approach. But I do feel the current expectation means almost everyone will hit this issue and get stuck/frustrated.

Is there a concrete reason why the situation cannot be improved for .NET 9 or even .NET 10 if that is needed.

Additional context

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions