Odkazy na agregace
Před voláním metody v odstupňovaném intervalu potřebujete nejprve odkaz na toto agregační. Odkaz na zrna je objekt proxy, který implementuje stejné rozhraní grain jako odpovídající třída zrnitosti. Zapouzdřuje logickou identitu (typ a jedinečný klíč) cílového agregace. Odkazy na agregace se používají k volání cílového agregace. Každý odkaz na agregační interval je jeden agregační (jedna instance třídy agregace), ale jeden může vytvořit více nezávislých odkazů na stejné agregační intervaly.
Vzhledem k tomu, že odkaz na agregační interval představuje logickou identitu cílového agregace, je nezávislá na fyzickém umístění agregace a zůstává platná i po úplném restartování systému. Vývojáři můžou používat odstupňované odkazy jako jakýkoli jiný objekt .NET. Lze ji předat metodě, použít jako návratovou hodnotu metody a dokonce ji uložit do trvalého úložiště.
Odkaz na agregační interval lze získat předáním identity agregace IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) metodě, kde T
je rozhraní grain a key
je jedinečným klíčem agregace v rámci typu.
Následuje příklad získání podrobného odkazu rozhraní definovaného IPlayerGrain
výše.
Z třídy zrnitosti:
// This would typically be read from an HTTP request parameter or elsewhere.
Guid playerId = Guid.NewGuid();
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);
Z Orleans klientského kódu:
// This would typically be read from an HTTP request parameter or elsewhere.
Guid playerId = Guid.NewGuid();
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
Odkazy na agregace obsahují tři informace:
- Typ zrnitosti, který jednoznačně identifikuje třídu zrnitosti.
- Klíč odstupňovaného intervalu, který jednoznačně identifikuje logickou instanci této třídy agregace.
- Rozhraní, které musí odkaz na agregační interval implementovat.
Poznámka:
Typ agregační hodnoty a klíč tvoří identitu odstupňovaného intervalu.
Všimněte si, že výše uvedená volání IGrainFactory.GetGrain přijali pouze dvě z těchto tří věcí:
- Rozhraní implementované odkazem
IPlayerGrain
na agregační. - Klíč odstupňovaného intervalu, což je hodnota
playerId
.
Přestože hlásíte, že odkaz na agregační interval obsahuje typ, klíč a rozhraní, příklady, které jsou k dispozici Orleans pouze s klíčem a rozhraním. Je to proto, že Orleans udržuje mapování mezi rozhraními zrn a typy zrn. Když požádáte o zadání objektu pro IShoppingCartGrain
výrobu zrna, Orleans projděte si jeho mapování a vyhledejte odpovídající typ agregačního intervalu, aby mohl vytvořit odkaz. To funguje, když existuje pouze jedna implementace rozhraní zrnitosti, ale pokud existuje více implementací, budete je muset v volání zrušit.GetGrain
Další informace najdete v další části s nejednoznačným rozlišením typu zrnitosti.
Poznámka:
Orleans generuje typy implementace odstupňované reference pro každé rozhraní v aplikaci během kompilace. Tyto referenční implementace agregačních odkazů dědí z Orleans.Runtime.GrainReference třídy. GetGrain
vrátí instance vygenerované Orleans.Runtime.GrainReference implementace odpovídající požadovanému rozhraní agregace.
Rozlišení nejednoznačného typu zrnitosti
Pokud existuje více implementací agregačních rozhraní, jako je například v následujícím příkladu, Orleans pokusí se určit zamýšlenou implementaci při vytváření referenčního intervalu. Představte si následující příklad, ve kterém existují dvě implementace ICounterGrain
rozhraní:
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
}
Následující volání GetGrain
vyvolá výjimku, protože Orleans neví, jak jednoznačně namapovat ICounterGrain
na jednu z tříd agregace.
// This will throw an exception: there is no unambiguous mapping from ICounterGrain to a grain class.
ICounterGrain myCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");
Vyvolá System.ArgumentException se následující zpráva:
Unable to identify a single appropriate grain type for interface ICounterGrain. Candidates: upcounter (UpCounterGrain), downcounter (DownCounterGrain)
Chybová zpráva vám řekne, která implementace podrobností Orleans má, která odpovídá požadovanému typu ICounterGrain
rozhraní agregační. Zobrazuje názvy typů zrnek (upcounter
a downcounter
) a také třídy zrnitosti (UpCounterGrain
a DownCounterGrain
).
Poznámka:
Názvy typů zrn v předchozí chybové zprávě upcounter
a downcounter
jsou odvozeny z názvů třídy zrnitosti UpCounterGrain
a DownCounterGrain
v uvedeném pořadí. Toto je výchozí chování Orleans a lze ho přizpůsobit přidáním [GrainType(string)]
atributu do třídy grain. Příklad:
[GrainType("up")]
public class UpCounterGrain : IUpCounterGrain { /* as above */ }
Existuje několik způsobů, jak tuto nejednoznačnost vyřešit podrobně v následujících pododdílech.
Disambiguating grain types using unique marker interfaces
Nejjasnější způsob, jak nejednoznačit tato zrnka, je poskytnout jim jedinečná rozhraní zrnitosti. Pokud například přidáme rozhraní IUpCounterGrain
do UpCounterGrain
třídy a přidáme rozhraní IDownCounterGrain
do DownCounterGrain
třídy, například v následujícím příkladu, můžeme přeložit správný odkaz na agregační interval předáním IUpCounterGrain
nebo IDownCounterGrain
voláním GetGrain<T>
namísto předání nejednoznačného ICounterGrain
typu.
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
}
Pokud chcete vytvořit odkaz na některou z možností, zvažte následující kód:
// 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");
Poznámka:
V předchozím příkladu jste vytvořili dva odkazy na agregační interval se stejným klíčem, ale různými typy zrn. První, uložená v myUpCounter
proměnné, je odkaz na agregační interval s ID upcounter/my-counter
. Druhá, uložená v myDownCounter
proměnné, je odkaz na agregační interval s ID downcounter/my-counter
. Jedná se o kombinaci typu zrnitosti a klíče zrnitosti, které jednoznačně identifikují zrnko. myUpCounter
Proto a myDownCounter
odkazovat na různá zrna.
Disambiguating grain types by providing a grain class prefix
Můžete zadat předponu IGrainFactory.GetGrainnázvu třídy zrnitosti, například:
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter", grainClassNamePrefix: "Up");
ICounterGrain myDownCounter = grainFactory.GetGrain<ICounterGrain>("my-counter", grainClassNamePrefix: "Down");
Určení výchozí implementace agregace pomocí konvence vytváření názvů
Při nejednoznačnosti více implementací stejného rozhraní Orleans zrnitosti vybere implementaci pomocí konvence odstranění úvodního "I" z názvu rozhraní. Pokud je ICounterGrain
například název rozhraní a existují dvě implementace, CounterGrain
a DownCounterGrain
zvolí Orleans se CounterGrain
, když se zobrazí výzva k zadání odkazu ICounterGrain
, jako v následujícím příkladu:
/// This will refer to an instance of CounterGrain, since that matches the convention.
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");
Určení výchozího typu agregace pomocí atributu
Atribut Orleans.Metadata.DefaultGrainTypeAttribute lze přidat do rozhraní odstupňované za účelem určení typu zrnitosti výchozí implementace pro toto rozhraní, jako v následujícím příkladu:
[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");
Disambiguating grain types by providing the resolved grain ID
Některé přetížení IGrainFactory.GetGrain přijmout argument typu Orleans.Runtime.GrainId. Při použití těchto přetížení Orleans není nutné mapovat z typu rozhraní na typ zrnitosti, a proto není potřeba vyřešit nejednoznačnost. Příklad:
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"));