Как создать универсальный тип, который должен наследовать от класса с универсальным типом в Blazor?
Я пытаюсь создать класс, который имеет 3 общих типа, и один из типов должен наследовать от другого класса, у которого есть другие 2 общих типа.
Что мне действительно нужно, так это то, что IForm
наследуется от FormComponent
так что все его методы реализованы.
Form.razor
@typeparam TForm
@typeparam TModel
@typeparam TResult
<EditForm Model="@Model" OnValidSubmit="@HandleValidSubmit">
@ChildContent
</EditForm>
Form.razor.cs
public partial class Form<TForm, TModel, TResult>
where TForm : FormComponent<TModel, TResult>
{
[Parameter]
public TForm FormRef { get; set; }
[Parameter]
public EventCallback<TResult> OnValidSubmit { get; set; }
[Parameter]
public TModel Model { get; set; }
// ...
// some other properties
}
FormComponent.cs
public abstract class FormComponent<TModel, TResult> : BaseDomComponent
{
[CascadingParameter]
public TModel Model { get; set; }
public abstract TResult OnValidSubmit();
// ...
// some other properties
}
Код, из которого я использую форму
<Form Model="@Entity" FormRef="@_formRef" OnValidSubmit="@HandleValidSubmit">
<XYZForm @ref="_formRef" />
<Button ButtonType="ButtonType.Submit">Submit</Button>
</Form>
Но это дает мне ошибку
Ошибка CS0314 Тип TForm нельзя использовать в качестве параметра типа TForm в универсальном типе или методе Form
. Преобразование упаковки или преобразование параметров типа из TForm в Core.Web.Base.FormComponent отсутствует.
Я искал эту ошибку во многих местах, но не нашел ни одного случая, когда было бы 3 общих типа. Я также читал документы, но не мог использовать их для решения своего дела.
2 ответа
Просто узнайте, что эта проблема связана с тем, что blazor еще не поддерживает ограничения типа.
@juharr спросил, не использую ли я его в другом месте. Я сказал нет, но на самом деле я использую его в компоненте Blazor, и у него еще нет такой поддержки;/
Сделайте свой универсальный компонент только компонентом класса. Таким образом вы можете добавить свои ограничения
Я думаю, что стоит поделиться найденным мной обходным путем - просто добавьте файл кода программной части в свой компонент и укажите там ограничения.
Кредиты на этот ответ, который привел меня к успеху...
Шаги по добавлению ограничения в
MyComponent.razor
:
Добавить -> Создать -> Класс, назовите файл
MyComponent.razor.cs
и убедитесь, что он создан в той же папке, что иMyComponent.razor
. Если все работает нормально, файл следует добавить как суб-файл илиMyComponent.razor.cs
...открыто
MyComponent.razor.cs
. Убедитесь, что пространство имен такое же, как у компонента (должно быть нормально, если класс был создан в той же папке)Отметьте класс как
public partial
и добавьте свои ограничения// убедитесь, что пространства имен соответствуют общедоступному частичному классу MyComponent, где TItem: MyBaseClass, new() {
Вот и все. И даже лучше, теперь я могу внедрить общий сервис в свой компонент в
MyComponent.razor
составная часть:
@typeparam TItem
@inject MyGenericService<TItem> _genericService;
Обратите внимание, что я зарегистрировал сервис в
Startup.cs
как синглтон (не тестировал область видимости, но тоже должен работать)...
// --- `Startup.cs` code
services.AddSingleton(new MyGenericService<MyObject>());
Надеюсь, это сработает для других, это сделало мои общие CRUD-формы НАМНОГО проще в работе и сохранило огромное количество дублированного кода и странных переключателей на вывод типа из общего управления!