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:
- Jenis biji-bijian, yang secara unik mengidentifikasi kelas biji-bijian.
- Kunci biji-bijian, yang secara unik mengidentifikasi instans logis dari kelas biji-bijian itu.
- 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"));