Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Bevor Sie eine Methode für ein Getreide aufrufen, benötigen Sie zuerst einen Verweis auf dieses Korn. Ein Kornverweis ist ein Proxyobjekt, das dieselbe Kornschnittstelle wie die entsprechende Kornklasse implementiert. Sie kapselt die logische Identität (Typ und eindeutiger Schlüssel) des Zielkorns. Sie verwenden Kornverweise, um Aufrufe an das Zielkorn zu tätigen. Jeder Kornverweis verweist auf ein einzelnes Korn (eine einzige Instanz der Kornklasse), Sie können jedoch mehrere unabhängige Bezüge auf dasselbe Korn erstellen.
Da ein Kornbezug die logische Identität des Zielkorns darstellt, ist es unabhängig von der physischen Position des Getreides und bleibt auch nach einem vollständigen Systemneustart gültig. Sie können Kornverweise wie jedes andere .NET-Objekt verwenden. Sie können sie an eine Methode übergeben, als Methodenrückgabewert verwenden und sogar im beständigen Speicher speichern.
Sie können einen Kornbezug erhalten, indem Sie die Identität eines Korns an die IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) Methode übergeben, wobei T es sich um die Kornschnittstelle handelt und key der eindeutige Schlüssel des Korns innerhalb seines Typs ist.
Die folgenden Beispiele zeigen, wie Sie einen Kornbezug für die IPlayerGrain zuvor definierte Schnittstelle abrufen.
Von innerhalb einer Kornklasse:
// This would typically be read from an HTTP request parameter or elsewhere.
Guid playerId = Guid.NewGuid();
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);
Von Orleans Clientcode:
// This would typically be read from an HTTP request parameter or elsewhere.
Guid playerId = Guid.NewGuid();
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
Getreideangaben enthalten drei Informationen:
- Der Korntyp, der die Kornklasse eindeutig identifiziert.
- Der Kornschlüssel, der eine logische Instanz dieser Kornklasse eindeutig identifiziert.
- Die Schnittstelle , die der Kornverweis implementieren muss.
Hinweis
Der Typ und der Schlüssel bilden die Identität des Korns.
Beachten Sie, dass die vorhergehenden Aufrufe IGrainFactory.GetGrain nur zwei dieser drei Dinge akzeptiert haben.
- Die Schnittstelle, die durch die Kornreferenz implementiert wird,
IPlayerGrain. - Der Kornschlüssel, der den Wert von
playerId.
Obwohl ein Kornbezug einen Korntyp, einen Schlüssel und eine Schnittstelle enthält, werden die Beispiele nur mit dem Orleans und der Schnittstelle bereitgestellt. Dies liegt daran, dass Orleans eine Zuordnung zwischen Grain-Schnittstellen und Grain-Typen aufrechterhält. Wenn Sie die Getreidefabrik nach IShoppingCartGrain fragen, konsultiert Orleans seine Zuordnung, um den entsprechenden Getreidetyp zu finden und den Verweis zu erstellen. Dies funktioniert, wenn nur eine Implementierung einer Kornschnittstelle vorhanden ist. Wenn jedoch mehrere Implementierungen vorhanden sind, müssen Sie sie im GetGrain Aufruf eindeutig machen. Weitere Informationen finden Sie im nächsten Abschnitt: Mehrdeutigkeit der Korntypauflösung.
Hinweis
Orleans generiert Getreidereferenzimplementierungstypen für jede Kornschnittstelle in Ihrer Anwendung während der Kompilierung. Diese Kornreferenzimplementierungen erben von der Orleans.Runtime.GrainReference Klasse.
GetGrain gibt Instanzen der generierten Orleans.Runtime.GrainReference Implementierung zurück, die der angeforderten Kornschnittstelle entspricht.
Mehrdeutigkeit der Korntypauflösung
Wenn mehrere Implementierungen einer Kornschnittstelle vorhanden sind, z. B. im folgenden Beispiel, versucht, Orleans die beabsichtigte Implementierung beim Erstellen eines Kornverweises zu bestimmen. Betrachten Sie das folgende Beispiel, in dem zwei Implementierungen der ICounterGrain Schnittstelle vorhanden sind:
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
}
Der folgende Aufruf von GetGrain löst eine Ausnahme aus, da Orleans nicht weiß, wie ICounterGrain eindeutig einer der Kornklassen zugeordnet werden kann.
// This will throw an exception: there is no unambiguous mapping from ICounterGrain to a grain class.
ICounterGrain myCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");
System.ArgumentException wird mit der folgenden Meldung ausgelöst:
Unable to identify a single appropriate grain type for interface ICounterGrain. Candidates: upcounter (UpCounterGrain), downcounter (DownCounterGrain)
Die Fehlermeldung teilt Ihnen mit, welche Kornimplementierungen gefunden wurden, die dem angeforderten Kornschnittstellentyp Orleans entsprechen. ICounterGrain Es zeigt die Korntypnamen (upcounter und downcounter) und die Getreideklassen (UpCounterGrain und DownCounterGrain).
Hinweis
Die Korntypnamen in der vorherigen Fehlermeldung upcounter und downcounter werden von den Kornklassennamen UpCounterGrain und DownCounterGrain beziehungsweise abgeleitet. Dies ist das Standardverhalten und Orleans kann durch Hinzufügen eines [GrainType(string)] Attributs zur Kornklasse angepasst werden. Beispiel:
[GrainType("up")]
public class UpCounterGrain : IUpCounterGrain { /* as above */ }
Es gibt mehrere Möglichkeiten, diese Mehrdeutigkeit zu beheben, die in den folgenden Unterabschnitten beschrieben ist.
Klärung von Korntypen durch eindeutige Markerschnittstellen
Der klarste Weg, diese Körner zu disambiguieren, besteht darin, ihnen einzigartige Getreideschnittstellen zu geben. Wenn Sie beispielsweise die Schnittstelle IUpCounterGrain zur Klasse UpCounterGrain und die Schnittstelle IDownCounterGrain zur Klasse DownCounterGrain hinzufügen, wie im folgenden Beispiel gezeigt, können Sie den korrekten Verweis auf das Objekt auflösen, indem Sie IUpCounterGrain oder IDownCounterGrain anstelle des mehrdeutigen Typs GetGrain<T> an den ICounterGrain-Aufruf übergeben.
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
}
Wenn Sie einen Verweis auf einen der Korn erstellen möchten, sollten Sie den folgenden Code berücksichtigen:
// 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");
Hinweis
Im vorhergehenden Beispiel haben Sie zwei Grain-Referenzen mit demselben Schlüssel, aber unterschiedlichen Grain-Typen erstellt. Der erste, der in der myUpCounter Variablen gespeichert ist, verweist auf das Korn mit der ID upcounter/my-counter. Die zweite, in der myDownCounter Variablen gespeicherte, verweist auf das Korn mit der ID downcounter/my-counter. Die Kombination aus Kornart und Kornschlüssel identifiziert ein Korn eindeutig. Daher beziehen sich myUpCounter und myDownCounter auf verschiedene Körner.
Unterscheidung der Getreidesorten durch Verwendung eines Getreideklassenpräfixes
Sie können ein Präfix für den Kornklassennamen, wie zum Beispiel IGrainFactory.GetGrain, angeben.
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter", grainClassNamePrefix: "Up");
ICounterGrain myDownCounter = grainFactory.GetGrain<ICounterGrain>("my-counter", grainClassNamePrefix: "Down");
Angeben der Standardkornimplementierung mithilfe der Benennungskonvention
Bei der Unterscheidung mehrerer Implementierungen derselben Grain-Schnittstelle wählt Orleans eine Implementierung aus, indem es die Konvention anwendet, ein führendes 'I' aus dem Schnittstellennamen zu entfernen. Wenn beispielsweise der Schnittstellenname ICounterGrain lautet und zwei Implementierungen CounterGrain und DownCounterGrain vorhanden sind, wählt OrleansCounterGrain aus, wenn nach einem Verweis auf ICounterGrain gefragt wird, wie im folgenden Beispiel gezeigt:
/// This will refer to an instance of CounterGrain, since that matches the convention.
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");
Angeben des Standardkorntyps mithilfe eines Attributs
Sie können das Orleans.Metadata.DefaultGrainTypeAttribute Attribut einer Kornschnittstelle hinzufügen, um den Korntyp der Standardimplementierung für diese Schnittstelle anzugeben, wie im folgenden Beispiel gezeigt:
[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");
Entfernen von Mehrdeutigkeiten bei Getreidetypen durch Angabe der aufgelösten Getreide-ID
Einige Überladungen von IGrainFactory.GetGrain akzeptieren ein Argument vom Typ Orleans.Runtime.GrainId. Wenn Sie diese Überladungen verwenden, muss Orleans nicht von einem Schnittstellentyp zu einem Grain-Typ zugeordnet werden, sodass keine Unklarheit aufgelöst werden muss. Beispiel:
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"));