Bagikan melalui


Referensi biji-bijian

Sebelum memanggil metode pada biji-bijian, Anda terlebih dahulu memerlukan referensi ke biji-bijian itu. Referensi biji-bijian adalah objek proksi yang mengimplementasikan antarmuka biji-bijian yang sama dengan kelas biji-bijian yang sesuai. Ini merangkum identitas logis (jenis dan kunci unik) dari butir target. Referensi biji-bijian digunakan untuk melakukan panggilan ke butir target. Setiap referensi biji-bijian adalah untuk satu biji-bijian (satu instans kelas biji-bijian), tetapi seseorang dapat membuat beberapa referensi independen ke biji-bijian yang sama.

Karena referensi biji-bijian mewakili identitas logis dari butir target, itu independen dari lokasi fisik biji-bijian, dan tetap valid bahkan setelah hidupkan ulang sistem secara lengkap. Pengembang dapat menggunakan referensi biji-bijian seperti objek .NET lainnya. Ini dapat diteruskan ke metode, digunakan sebagai nilai pengembalian metode, dan bahkan disimpan ke penyimpanan persisten.

Referensi biji-bijian dapat diperoleh dengan meneruskan identitas biji-bijian ke IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) metode , di mana T merupakan antarmuka biji-bijian dan key merupakan kunci unik dari biji-bijian dalam jenis tersebut.

Berikut ini adalah contoh cara mendapatkan referensi butir antarmuka yang IPlayerGrain ditentukan di atas.

Dari dalam kelas biji-bijian:

// This would typically be read from an HTTP request parameter or elsewhere.
Guid playerId = Guid.NewGuid();
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);

Dari Orleans kode klien:

// This would typically be read from an HTTP request parameter or elsewhere.
Guid playerId = Guid.NewGuid();
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);

Referensi biji-bijian berisi tiga informasi:

  1. Jenis biji-bijian, yang secara unik mengidentifikasi kelas biji-bijian.
  2. Kunci biji-bijian, yang secara unik mengidentifikasi instans logis dari kelas biji-bijian itu.
  3. Antarmuka yang harus diterapkan referensi biji-bijian.

Catatan

Jenis biji-bijian dan kunci membentuk identitas biji-bijian.

Perhatikan bahwa panggilan di atas hanya IGrainFactory.GetGrain menerima dua dari tiga hal tersebut:

  • Antarmuka yang diimplementasikan oleh referensi biji-bijian, IPlayerGrain.
  • Kunci biji-bijian, yang merupakan nilai dari playerId.

Meskipun menyatakan bahwa referensi biji-bijian berisi jenis biji-bijian, kunci, dan antarmuka, contoh hanya disediakan Orleans dengan kunci dan antarmuka. Itu karena Orleans mempertahankan pemetaan antara antarmuka biji-bijian dan jenis biji-bijian. Ketika Anda meminta pabrik biji-bijian untuk IShoppingCartGrain, Orleans konsultasikan pemetaannya untuk menemukan jenis biji-bijian yang sesuai sehingga dapat membuat referensi. Ini berfungsi ketika hanya ada satu implementasi antarmuka biji-bijian, tetapi jika ada beberapa implementasi, maka Anda harus membedakannya dalam GetGrain panggilan. Untuk informasi selengkapnya, lihat bagian berikutnya, resolusi jenis butir yang tidak ambigu.

Catatan

Orleans menghasilkan jenis implementasi referensi biji-bijian untuk setiap antarmuka biji-bijian dalam aplikasi Anda selama kompilasi. Implementasi referensi biji-bijian ini mewarisi dari Orleans.Runtime.GrainReference kelas . GetGrain mengembalikan instans implementasi yang dihasilkan Orleans.Runtime.GrainReference yang sesuai dengan antarmuka biji-bijian yang diminta.

Resolusi jenis biji-bijian yang tidak ambigu

Ketika ada beberapa implementasi antarmuka biji-bijian, seperti dalam contoh berikut, Orleans upaya untuk menentukan implementasi yang dimaksudkan saat membuat referensi biji-bijian. Pertimbangkan contoh berikut, di mana ada dua implementasi ICounterGrain antarmuka:

public interface ICounterGrain : IGrainWithStringKey
{
    ValueTask<int> UpdateCount();
}

public class UpCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(++_count); // Increment count
}

public class DownCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(--_count); // Decrement count
}

Panggilan berikut untuk GetGrain akan melemparkan pengecualian karena Orleans tidak tahu cara memetakan ICounterGrain secara tidak ambigu ke salah satu kelas biji-bijian.

// This will throw an exception: there is no unambiguous mapping from ICounterGrain to a grain class.
ICounterGrain myCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");

Akan System.ArgumentException dilemparkan dengan pesan berikut:

Unable to identify a single appropriate grain type for interface ICounterGrain. Candidates: upcounter (UpCounterGrain), downcounter (DownCounterGrain)

Pesan kesalahan memberi tahu Anda implementasi Orleans grain mana yang cocok dengan jenis antarmuka butir yang diminta, ICounterGrain. Ini menunjukkan nama jenis biji-bijian (upcounter dan downcounter) serta kelas biji-bijian (UpCounterGrain dan DownCounterGrain).

Catatan

Nama jenis biji-bijian dalam pesan kesalahan sebelumnya, upcounter dan , masing-masing berasal dari nama kelas biji-bijian DownCounterGrain UpCounterGrain.downcounter Ini adalah perilaku default dan Orleans dapat disesuaikan dengan menambahkan [GrainType(string)] atribut ke kelas biji-bijian. Contohnya:

[GrainType("up")]
public class UpCounterGrain : IUpCounterGrain { /* as above */ }

Ada beberapa cara untuk mengatasi ambiguitas ini yang dirinci dalam sub-bagian berikut.

Memisahkan jenis butir menggunakan antarmuka penanda unik

Cara paling jelas untuk membedakan biji-bijian ini adalah dengan memberi mereka antarmuka biji-bijian yang unik. Misalnya, jika kita menambahkan antarmuka IUpCounterGrain ke UpCounterGrain kelas dan menambahkan antarmuka IDownCounterGrain ke DownCounterGrain kelas, seperti dalam contoh berikut, maka kita dapat menyelesaikan referensi biji-bijian yang benar dengan meneruskan IUpCounterGrain atau IDownCounterGrain ke GetGrain<T> panggilan alih-alih melewati jenis ambigu ICounterGrain .

public interface ICounterGrain : IGrainWithStringKey
{
    ValueTask<int> UpdateCount();
}

// Define unique interfaces for our implementations
public interface IUpCounterGrain : ICounterGrain, IGrainWithStringKey {}
public interface IDownCounterGrain : ICounterGrain, IGrainWithStringKey {}

public class UpCounterGrain : IUpCounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(++_count); // Increment count
}

public class DownCounterGrain : IDownCounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(--_count); // Decrement count
}

Untuk membuat referensi ke salah satu butir, pertimbangkan kode berikut:

// Get a reference to an UpCounterGrain.
ICounterGrain myUpCounter = grainFactory.GetGrain<IUpCounterGrain>("my-counter");

// Get a reference to a DownCounterGrain.
ICounterGrain myDownCounter = grainFactory.GetGrain<IDownCounterGrain>("my-counter");

Catatan

Dalam contoh sebelumnya, Anda membuat dua referensi biji-bijian dengan kunci yang sama, tetapi jenis butir yang berbeda. Yang pertama, disimpan dalam myUpCounter variabel, adalah referensi ke biji-bijian dengan id upcounter/my-counter. Yang kedua, disimpan dalam myDownCounter variabel, adalah referensi ke biji-bijian dengan id downcounter/my-counter. Ini adalah kombinasi jenis biji-bijian dan kunci biji-bijian yang secara unik mengidentifikasi biji-bijian. Oleh karena itu, myUpCounter dan myDownCounter lihat biji-bijian yang berbeda.

Membedakan jenis biji-bijian dengan menyediakan awalan kelas biji-bijian

Anda dapat memberikan awalan nama kelas grain ke IGrainFactory.GetGrain, misalnya:

ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter", grainClassNamePrefix: "Up");
ICounterGrain myDownCounter = grainFactory.GetGrain<ICounterGrain>("my-counter", grainClassNamePrefix: "Down");

Menentukan implementasi grain default menggunakan konvensi penamaan

Saat membedakan beberapa implementasi antarmuka butir yang sama, Orleans akan memilih implementasi menggunakan konvensi stripping 'I' terkemuka dari nama antarmuka. Misalnya, jika nama antarmuka adalah ICounterGrain dan ada dua implementasi, CounterGrain dan DownCounterGrain, Orleans akan memilih CounterGrain saat dimintai referensi ke ICounterGrain, seperti dalam contoh berikut:

/// This will refer to an instance of CounterGrain, since that matches the convention.
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");

Menentukan jenis butir default menggunakan atribut

Atribut Orleans.Metadata.DefaultGrainTypeAttribute dapat ditambahkan ke antarmuka biji-bijian untuk menentukan jenis grain implementasi default untuk antarmuka tersebut, seperti dalam contoh berikut:

[DefaultGrainType("up-counter")]
public interface ICounterGrain : IGrainWithStringKey
{
    ValueTask<int> UpdateCount();
}

[GrainType("up-counter")]
public class UpCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(++_count); // Increment count
}

[GrainType("down-counter")]
public class DownCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(--_count); // Decrement count
}
/// This will refer to an instance of UpCounterGrain, due to the [DefaultGrainType("up-counter"')] attribute
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");

Mendisambiguasi jenis biji-bijian dengan memberikan id biji-bijian yang diselesaikan

Beberapa kelebihan beban IGrainFactory.GetGrain menerima argumen jenis Orleans.Runtime.GrainId. Saat menggunakan kelebihan beban ini, Orleans tidak perlu memetakan dari jenis antarmuka ke jenis biji-bijian dan oleh karena itu tidak ada ambiguitas untuk diselesaikan. Contohnya:

public interface ICounterGrain : IGrainWithStringKey
{
    ValueTask<int> UpdateCount();
}

[GrainType("up-counter")]
public class UpCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(++_count); // Increment count
}

[GrainType("down-counter")]
public class DownCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(--_count); // Decrement count
}
// This will refer to an instance of UpCounterGrain, since "up-counter" was specified as the grain type
// and the UpCounterGrain uses [GrainType("up-counter")] to specify its grain type.
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>(GrainId.Create("up-counter", "my-counter"));