Bagikan melalui


dukungan jenis generik komponen ASP.NET Core Razor

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Artikel ini menjelaskan dukungan jenis generik dalam Razor komponen.

Jika Anda baru menggunakan jenis generik, lihat Kelas dan metode generik (Panduan C#) untuk panduan umum tentang penggunaan generik sebelum membaca artikel ini.

Contoh kode dalam artikel ini hanya tersedia untuk rilis .NET terbaru di Blazor aplikasi sampel.

Dukungan parameter jenis generik

Arahan @typeparam mendeklarasikan parameter jenis generik untuk kelas komponen yang dihasilkan:

@typeparam TItem

Sintaks C# dengan batasan jenis where didukung:

@typeparam TEntity where TEntity : IEntity

Dalam contoh berikut, ListItems1 komponen secara generik di ketik sebagai TExample, yang mewakili jenis ExampleList koleksi.

ListItems1.razor:

@typeparam TExample

<h2>List Items 1</h2>

@if (ExampleList is not null)
{
    <ul style="color:@Color">
        @foreach (var item in ExampleList)
        {
            <li>@item</li>
        }
    </ul>

    <p>
        Type of <code>TExample</code>: @typeof(TExample)
    </p>
}

@code {
    [Parameter]
    public string? Color { get; set; }

    [Parameter]
    public IEnumerable<TExample>? ExampleList { get; set; }
}

Komponen berikut merender dua ListItems1 komponen:

  • Data string atau bilangan bulat ditetapkan ke parameter ExampleList dari setiap komponen.
  • string atau int jenis yang cocok dengan jenis data yang ditetapkan diatur untuk parameter jenis (TExample) setiap komponen.

Generics1.razor:

@page "/generics-1"

<PageTitle>Generics 1</PageTitle>

<h1>Generic Type Example 1</h1>

<ListItems1 Color="blue"
            ExampleList="@(new List<string> { "Item 1", "Item 2" })"
            TExample="string" />

<ListItems1 Color="red"
            ExampleList="@(new List<int> { 1, 2 })"
            TExample="int" />

Untuk informasi lebih lanjut, lihat Referensi sintaks Razor untuk ASP.NET Core. Untuk contoh pengetikan umum dengan komponen template, lihat komponen template Blazor ASP.NET Core.

Dukungan jenis generik bertingkat

Komponen leluhur dapat mengkaskade parameter jenis berdasarkan nama ke keturunan menggunakan atribut [CascadingTypeParameter]. Atribut ini memungkinkan inferensi jenis generik untuk menggunakan parameter jenis yang ditentukan secara otomatis dengan keturunan yang memiliki parameter jenis dengan nama yang sama.

Dengan menambahkan @attribute [CascadingTypeParameter(...)] ke komponen, argumen jenis generik yang ditentukan secara otomatis digunakan oleh keturunan yang:

  • Disarangkan sebagai konten turunan untuk komponen dalam dokumen .razor yang sama.
  • Deklarasikan juga @typeparam dengan nama yang sama persis.
  • Jangan memiliki nilai lain yang disediakan secara eksplisit atau disimpulkan secara implisit untuk parameter jenis. Jika nilai lain diberikan atau disimpulkan, ini lebih diutamakan daripada jenis generik yang dikaskade.

Saat menerima parameter jenis berskala, komponen mendapatkan nilai parameter dari leluhur terdekat yang memiliki [CascadingTypeParameter] atribut dengan nama yang cocok. Parameter jenis generik yang dikaskade diganti dalam sub-pohon tertentu.

Pencocokan hanya dilakukan berdasarkan nama. Oleh karena itu, sebaiknya hindari parameter jenis generik yang dikaskade dengan nama generik, misalnya T atau TItem. Jika pengembang memilih parameter jenis kaskade, mereka secara implisit menjanjikan bahwa namanya cukup unik agar tidak bentrok dengan parameter jenis yang dikaskade lainnya dari komponen yang tidak terkait.

Jenis generik dapat disalin ke komponen turunan dengan salah satu pendekatan berikut untuk komponen leluhur (induk), yang ditunjukkan dalam dua sub-bagian berikut:

  • Secara eksplisit mengatur jenis generik yang dikaskade.
  • Menyimpulkan jenis generik yang dikaskade.

Subbagian berikut memberikan contoh pendekatan sebelumnya menggunakan komponen berikut ListDisplay1 . Komponen menerima dan merender data daftar yang ditik secara generis sebagai TExample. Untuk membuat setiap instans ListDisplay1 menonjol, parameter komponen tambahan mengontrol warna daftar.

ListDisplay1.razor:

@typeparam TExample

@if (ExampleList is not null)
{
    <ul style="color:@Color">
        @foreach (var item in ExampleList)
        {
            <li>@item</li>
        }
    </ul>
}

@code {
    [Parameter]
    public string? Color { get; set; }

    [Parameter]
    public IEnumerable<TExample>? ExampleList { get; set; }
}

Jenis generik eksplisit berdasarkan komponen leluhur

Demonstrasi di bagian ini mengkaskade jenis secara eksplisit untuk TExample.

Catatan

Bagian ini menggunakan komponen sebelumnya ListDisplay1 di bagian dukungan jenis generik Berskala.

Komponen ListItems2 berikut menerima data dan mengkaskade parameter jenis generik bernama TExample ke komponen keturunannya. Dalam komponen induk yang akan datang, komponen ListItems2 digunakan untuk menampilkan data daftar dengan komponen ListDisplay1 sebelumnya.

ListItems2.razor:

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

<h2>List Items 2</h2>

@ChildContent

<p>
    Type of <code>TExample</code>: @typeof(TExample)
</p>

@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

Komponen induk berikut mengatur konten anak (RenderFragment) dari dua ListItems2 komponen yang menentukan ListItems2 jenis (TExample), yang bertingkat ke komponen turunan. ListDisplay1 komponen dirender dengan data item daftar yang ditampilkan dalam contoh. Data string digunakan dengan komponen ListItems2 pertama, dan data bilangan bulat digunakan dengan komponen ListItems2 kedua.

Generics2.razor:

@page "/generics-2"

<PageTitle>Generics 2</PageTitle>

<h1>Generic Type Example 2</h1>

<ListItems2 TExample="string">
    <ListDisplay1 Color="blue" 
                  ExampleList="@(new List<string> { "Item 1", "Item 2" })" />
    <ListDisplay1 Color="red" 
                  ExampleList="@(new List<string> { "Item 3", "Item 4" })" />
</ListItems2>

<ListItems2 TExample="int">
    <ListDisplay1 Color="blue" 
                  ExampleList="@(new List<int> { 1, 2 })" />
    <ListDisplay1 Color="red" 
                  ExampleList="@(new List<int> { 3, 4 })" />
</ListItems2>

Menentukan jenis secara eksplisit juga memungkinkan penggunaan nilai dan parameter kaskade untuk menyediakan data ke komponen turunan, seperti yang ditunjukkan oleh demonstrasi berikut.

ListDisplay2.razor:

@typeparam TExample

@if (ExampleList is not null)
{
    <ul style="color:@Color">
        @foreach (var item in ExampleList)
        {
            <li>@item</li>
        }
    </ul>
}

@code {
    [Parameter]
    public string? Color { get; set; }

    [CascadingParameter]
    protected IEnumerable<TExample>? ExampleList { get; set; }
}

ListItems3.razor:

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

<h2>List Items 3</h2>

@ChildContent

@if (ExampleList is not null)
{
    <ul style="color:green">
        @foreach (var item in ExampleList)
        {
            <li>@item</li>
        }
    </ul>

    <p>
        Type of <code>TExample</code>: @typeof(TExample)
    </p>
}

@code {
    [CascadingParameter]
    protected IEnumerable<TExample>? ExampleList { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

Saat melakukan kaskade data dalam contoh berikut, jenisnya harus diberikan ke komponen .

Generics3.razor:

@page "/generics-3"

<PageTitle>Generics 3</PageTitle>

<h1>Generic Type Example 3</h1>

<CascadingValue Value="stringData">
    <ListItems3 TExample="string">
        <ListDisplay2 Color="blue" />
        <ListDisplay2 Color="red" />
    </ListItems3>
</CascadingValue>

<CascadingValue Value="integerData">
    <ListItems3 TExample="int">
        <ListDisplay2 Color="blue" />
        <ListDisplay2 Color="red" />
    </ListItems3>
</CascadingValue>

@code {
    private List<string> stringData = new() { "Item 1", "Item 2" };
    private List<int> integerData = new() { 1, 2 };
}

Ketika beberapa jenis generik dikaskade, nilai untuk semua jenis generik dalam set harus diteruskan. Dalam contoh berikut, TItem, TValue, dan TEdit adalah jenis generik GridColumn, tetapi komponen induk yang menempatkan GridColumn tidak menentukan jenis TItem:

<GridColumn TValue="string" TEdit="TextEdit" />

Contoh sebelumnya menghasilkan kesalahan waktu kompilasi bahwa komponen GridColumn tidak memiliki parameter jenis TItem. Kode yang valid menentukan semua jenis:

<GridColumn TValue="string" TEdit="TextEdit" TItem="User" />

Menyimpulkan jenis generik berdasarkan komponen leluhur

Demonstrasi di bagian ini mengaskade jenis yang disimpulkan untuk TExample.

Catatan

Bagian ini menggunakan ListDisplay komponen di bagian dukungan jenis generik Cascaded.

ListItems4.razor:

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

<h2>List Items 4</h2>

@ChildContent

@if (ExampleList is not null)
{
    <ul style="color:green">
        @foreach (var item in ExampleList)
        {
            <li>@item</li>
        }
    </ul>

    <p>
        Type of <code>TExample</code>: @typeof(TExample)
    </p>
}

@code {
    [Parameter]
    public IEnumerable<TExample>? ExampleList { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

Komponen berikut dengan jenis kaskade yang disimpulkan menyediakan data yang berbeda untuk ditampilkan.

Generics4.razor:

@page "/generics-4"

<PageTitle>Generics 4</PageTitle>

<h1>Generic Type Example 4</h1>

<ListItems4 ExampleList="@(new List<string> { "Item 5", "Item 6" })">
    <ListDisplay1 Color="blue" 
                  ExampleList="@(new List<string> { "Item 1", "Item 2" })" />
    <ListDisplay1 Color="red" 
                  ExampleList="@(new List<string> { "Item 3", "Item 4" })" />
</ListItems4>

<ListItems4 ExampleList="@(new List<int> { 5, 6 })">
    <ListDisplay1 Color="blue" 
                  ExampleList="@(new List<int> { 1, 2 })" />
    <ListDisplay1 Color="red" 
                  ExampleList="@(new List<int> { 3, 4 })" />
</ListItems4>

Komponen berikut dengan jenis kaskade yang disimpulkan menyediakan data yang sama untuk ditampilkan. Contoh berikut secara langsung menetapkan data ke komponen.

Generics5.razor:

@page "/generics-5"

<PageTitle>Generics 5</PageTitle>

<h1>Generic Type Example 5</h1>

<ListItems4 ExampleList="stringData">
    <ListDisplay1 Color="blue" ExampleList="stringData" />
    <ListDisplay1 Color="red" ExampleList="stringData" />
</ListItems4>

<ListItems4 ExampleList="integerData">
    <ListDisplay1 Color="blue" ExampleList="integerData" />
    <ListDisplay1 Color="red" ExampleList="integerData" />
</ListItems4>

@code {
    private List<string> stringData = new() { "Item 1", "Item 2" };
    private List<int> integerData = new() { 1, 2 };
}