c# - 通用 Blazor 组件的编译器错误
问题描述
我select
在 Blazor 中定义了一个自定义组件,如下所示:
public class BetterInputSelect<TItem> : InputBase<TItem>
{
[Parameter]
public IEnumerable<TItem> Data { get; set; } = new List<TItem>();
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0, "select");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "class", CssClass);
builder.AddAttribute(3, "value", BindConverter.FormatValue(CurrentValueAsString));
builder.AddAttribute(4, "onchange", EventCallback.Factory.CreateBinder<string>(
this, value => CurrentValueAsString = value, CurrentValueAsString!, null));
foreach (var item in this.Data)
{
builder.OpenElement(5, "option");
builder.AddAttribute(6, "value", item!.ToString());
builder.AddContent(7, this.FindDisplayName(item));
builder.CloseElement();
}
builder.CloseElement();
}
protected override bool TryParseValueFromString(string? value, out TItem result, out string validationErrorMessage)
{
// Check for enums first.
if (typeof(TItem).IsEnum && BindConverter.TryConvertTo(value, CultureInfo.CurrentCulture, out TItem? parsedValue))
{
result = parsedValue!;
validationErrorMessage = null!;
return true;
}
// Other types here
// ...
result = default!;
validationErrorMessage = $"The {FieldIdentifier.FieldName} field is not valid.";
return false;
}
private string FindDisplayName(TItem value)
{
return value switch
{
null => string.Empty,
Enum @enum => @enum.GetDescription(),
_ => value.ToString() ?? string.Empty
};
}
}
然后可以这样使用:
<BetterInputSelect Data="@Reasons" @bind-Value="@Reason" />
其中Reasons
和Reason
定义如下:
public SomeReason Reason { get; set; }
private IEnumerable<SomeReason>? Reasons { get; set; }
...
public enum SomeReason
{
...
}
只要绑定的值@bind-Value
不可为空,这将非常有效。当我做:
public SomeReason? Reason { get; set; }
我得到一个编译时错误:
[CS0411] The type arguments for method
'TypeInference.CreateBetterInputSelect_0<TItem>(RenderTreeBuilder, int, int, IEnumerable<TItem>, int, TItem, int, EventCallback<TItem>, int, Expression<Func<TItem>>)'
cannot be inferred from the usage. Try specifying the type arguments explicitly.
我可以简单地不绑定到可为空的属性,还是有办法让编译器对我错过的感到高兴?
编辑
如果我尝试像这样明确定义类型:
<BetterInputSelect
Data="@Reasons"
@bind-Value="@Reason"
TItem="SomeReason" />
然后我得到以下编译器错误:
[CS1503] Argument 1: cannot convert from 'SomeReason?' to 'SomeReason'
[CS1503] Argument 2: cannot convert from 'Microsoft.AspNetCore.Components.EventCallback<SomeReason?>' to 'Microsoft.AspNetCore.Components.EventCallback'
[CS0266] Cannot implicitly convert type 'SomeReason?' to 'SomeReason'. An explicit conversion exists (are you missing a cast?)
[CS1662] Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type
解决方案
解决方案如下:
在BetterInputSelect<TItem>
:
// Was:
// [Parameter]
// public IEnumerable<TItem> Data { get; set; } = new List<TItem>();
[Parameter]
public IEnumerable<TItem?> Data { get; set; } = new List<TItem?>();
在我看来,我做了:
<BetterInputSelect
Data="@(Reasons as IEnumerable<SomeReason?>)"
TItem="SomeReason?"
@bind-Value="@Reason" />
在@Reason
可空和不可空时有效。不可为空的当然不需要强制转换和显式类型定义:
<BetterInputSelect
Data="@Reasons"
@bind-Value="@Reason" />
推荐阅读
- ios - 从其他视图导航后,我的程序化侧边菜单的导航栏不会出现
- python - 在 Django 中向 UserCreationForm 添加占位符
- unity3d - 统一创建匿名高分者
- java - java中的mongodb,如何在聚合函数中使用日期范围
- javascript - 破碎的 Jquery Ui 风格的 Datepicker
- c++ - 在类中初始化静态常量数组 - C++
- python - 实现 SVM RBF
- reactjs - 当我只在同一个基本 URL 上使用 API 路由时,为什么会得到“仅支持绝对 URL”?
- java - Kafka在java中将hashmap序列化为json
- r - 0.5<0.5 在 R 中返回 TRUE?