【发布时间】:2021-09-10 02:41:18
【问题描述】:
我正在使用Language-Ext library 创建一个表示三种状态之一的通用联合类型...
[Union]
public interface LoadingOption<T> {
LoadingOption<T> Loading();
LoadingOption<T> Loaded(T value);
LoadingOption<T> NotLoaded();
}
然后我有一个 Blazor 组件,它将显示三个渲染片段之一,具体取决于联合实例表示的三个状态中的哪一个...
@typeparam T
@(Data switch {
Loading<T> => Loading,
Loaded<T> t => Loaded(t.Value),
NotLoaded<T> => NotLoaded,
_ => Loading
})
@code {
[Parameter]
public LoadingOption<T> Data { get; set; }
[Parameter]
public RenderFragment<Loading<T>> Loading { get; set; }
[Parameter]
public RenderFragment<Loaded<T>> Loaded { get; set; }
[Parameter]
public RenderFragment<NotLoaded<T>> NotLoaded { get; set; }
}
请注意,switch 语句中的默认情况需要在页面首次加载时防止异常非详尽的 switch 表达式未能匹配其输入。
但是,当我尝试使用此组件时,HTML 永远不会呈现。相反,我在页面上看到Microsoft.AspNetCore.Components.RenderFragment,这听起来像是将RenderFragment 视为普通对象,而不是RenderFragment
Loader.razor 组件的示例用法如下...
@page "/LoadingOptionSample"
<h3>Loader sample</h3>
<p><button class="btn btn-primary" @onclick="LoadCustomerFound">Existing customer</button>
<button class="btn btn-secondary" @onclick="LoadCustomerNotFound">No such customer</button></p>
<Loader Data="_customer" Context="customer">
<Loading>
<p>Please wait while we look for the customer...</p>
</Loading>
<Loaded>
<p>Found @customer.Value.Name (id: @customer.Value.Id), who is @customer.Value.Age years old</p>
</Loaded>
<NotLoaded>
<p>Big flop, we can't find him</p>
</NotLoaded>
</Loader>
@code {
private LoadingOption<Customer> _customer;
private async Task LoadCustomerFound() {
_customer = new Loading<Customer>();
// Simulate database access so we can see the Loading HTML...
await Task.Delay(2000);
_customer = new Loaded<Customer>(new Customer(1, "Jim Spriggs", 42));
}
private async Task LoadCustomerNotFound() {
_customer = new Loading<Customer>();
await Task.Delay(2000);
_customer = new NotLoaded<Customer>();
}
}
单击其中一个按钮后,页面如下所示...
不管我点击哪个按钮,输出都是一样的,不会改变。这支持了我的怀疑,即 Blazor 没有将 RenderFragment 视为这样,而是将其视为普通的 .NET 对象并通过调用 ToString() 来呈现它,这就是我看到类型而不是内容的原因。
如果我做这个的非通用版本,它工作正常。
注意,我已经多次重启VS,以及在单独的项目中尝试过,但结果总是一样,所以看起来问题封装在上面显示的三个文件中。
有人知道我做错了什么吗?谢谢
更新我尝试使用常规的 switch 语句,而不是 switch 表达式,但它没有任何区别。然而,在测试这个时,我发现如果我根本没有switch,那么就这样做了......
@NotLoaded
...然后我仍然得到页面上显示的类型。
【问题讨论】:
-
[union]与 switch 表达式的工作方式不匹配。您的返回值并非都属于同一类型。试试传统的 switch 语句。 -
@henk 感谢您的建议,但没有任何区别。请查看我更新的问题,因为您的建议导致了一个可能很重要的发现。再次感谢。
-
您缺少一个参数。它应该类似于
@NotLoaded(Data),尽管它可能无法编译。 -
@HenkHolterman
NotLoaded和Loading不带参数,或者至少不应该带参数。只有Loaded带了一个参数,即已经加载的实体。如果您查看[Union]代码,您可以看到这一点。不确定我是否在 Blazor 组件中获得了RenderFragment声明。也许这就是它出错的地方。但是,如果这是问题所在,我会期望NotLoaded和Loading工作,或Loaded工作。实际上,这三个都只是显示RenderFragment的类型,而不是按照我的意愿渲染它。再次感谢,还有什么想法吗? -
有什么理由不能使用具有三个状态和三个 RenderFragment 的通用“加载”组件?然后从父级设置状态?
标签: c# blazor blazor-server-side language-ext