Sdílet prostřednictvím


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:

  1. Typ zrnitosti, který jednoznačně identifikuje třídu zrnitosti.
  2. Klíč odstupňovaného intervalu, který jednoznačně identifikuje logickou instanci této třídy agregace.
  3. 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 IPlayerGrainna 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 IShoppingCartGrainvý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 ICounterGrainrozhraní 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 downcounterjsou 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 DownCounterGrainzvolí 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"));