Description
Describe the bug
When a generic Blazor component has a Generic Parameter with an additional constraint, it can't infer it's type correctly.
Example:
Define a basic class and interface
public class MyClass : IMyInterface
{
}
public interface IMyInterface
{
}
Say we have 2 components. (I will only show the code behind.)
partial class InferComponent<T>
{
[Parameter] public IEnumerable<T> Items { get; set; }
}
And
partial class NotInferComponent<T>
where T : IMyInterface
{
[Parameter] public IEnumerable<T> Items { get; set; }
}
And then use these 2 classes
<InferComponent Items="new MyClass[] { new MyClass() }"></InferComponent>
<NotInferComponent Items="new MyClass[] { new MyClass() }"></NotInferComponent>
InferComponent will correctly infer that it's T
is MyClass
But NotInferComponent will report an error:
(The type 'T' cannot be used as type parameter 'T' in the generic type or method 'NotInferComponent'. There is no boxing conversion or type parameter conversion from 'T' to 'BlazorApp1.IMyInterface'. BlazorApp1)
The problem lies in the autogenerated razor.g.cs classes, and especially where it tries to get its type by type inference.
Below is part of the generated code. I added a remark with what is missing.
I think the solution would be that whenever the Blazor component that it wants to construct has additional constraints, these constraints should be added to the CreateComponentName function as well.
namespace __Blazor.BlazorApp1.Pages.Index
{
#line hidden
internal static class TypeInference
{
public static void CreateInferComponent_0<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
{
__builder.OpenComponent<global::BlazorApp1.Components.InferComponent<T>>(seq);
__builder.AddAttribute(__seq0, "Items", __arg0);
__builder.CloseComponent();
}
public static void CreateNotInferComponent_1<T>(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder
__builder, int seq, int __seq0, global::System.Collections.Generic.IEnumerable<T> __arg0)
//Where T : IMyInterface <--- This is missing
{
__builder.OpenComponent<global::BlazorApp1.Components.NotInferComponent<T>>(seq);
__builder.AddAttribute(__seq0, "Items", __arg0);
__builder.CloseComponent();
}
}
}
I don't think it's a duplicate of #8433, as the constraint on components itself works, it's the type inference that fails
Workaround
there is a workaround for this issue
add
T="MyClass"
as in
<NotInferComponent Items="new MyClass[] { new MyClass() }" T="MyClass"></NotInferComponent>
Will make it compile.
So we have a temporary solution for this issue, although I think it's confusing for the end-user to have to add T="MyClass"
only when T has an additional constraint.
To Reproduce
Repro: https://github.com/MariovanZeist/BlazorTypeinference
(based on Simple Blazor server app template)
Further technical details
Aspnetcore 5 preview 8
.NET SDK (reflecting any global.json):
Version: 5.0.100-preview.8.20417.9
Commit: fc62663a35
Runtime Environment:
OS Name: Windows
OS Version: 10.0.18363
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\5.0.100-preview.8.20417.9\
Host (useful for support):
Version: 5.0.0-preview.8.20407.11
Commit: bf456654f9
.NET SDKs installed:
3.0.100 [C:\Program Files\dotnet\sdk]
3.1.201 [C:\Program Files\dotnet\sdk]
3.1.400-preview-015203 [C:\Program Files\dotnet\sdk]
3.1.401 [C:\Program Files\dotnet\sdk]
5.0.100-preview.8.20417.9 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0-preview.8.20414.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.0-preview.8.20407.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.0-preview.8.20411.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
VS 2019 16.8 Preview 2.1