Udostępnij przez


Rozszerzenia ziarna

Rozszerzenia ziaren zapewniają sposób dodawania dodatkowego zachowania dla ziaren. Rozszerzając ziarno za pomocą interfejsu pochodzącego z IGrainExtensionprogramu , do ziarna można dodać nowe metody i funkcje.

W tym artykule przedstawiono dwa przykłady rozszerzeń ziarna. W pierwszym przykładzie pokazano, jak dodać metodę Deactivate do wszystkich ziaren, której można użyć do dezaktywacji ziarna. W drugim przykładzie pokazano, jak dodać metody GetState i SetState do dowolnego ziarna, umożliwiając manipulowanie stanem wewnętrznym ziarna.

Przykład dezaktywacji rozszerzenia

W tym przykładzie pokazano automatyczne dodawanie Deactivate metody do wszystkich ziaren. Użyj metody , aby dezaktywować ziarno; akceptuje ciąg jako parametr komunikatu. Orleans ziarna obsługują już tę funkcję za pośrednictwem interfejsu IGrainManagementExtension . Niemniej jednak w tym przykładzie pokazano, jak można dodać tę lub podobną funkcjonalność.

Dezaktywowanie interfejsu rozszerzenia

Zacznij od zdefiniowania interfejsu IGrainDeactivateExtension zawierającego metodę Deactivate . Interfejs musi pochodzić z klasy IGrainExtension.

public interface IGrainDeactivateExtension : IGrainExtension
{
    Task Deactivate(string msg);
}

Dezaktywowanie implementacji rozszerzenia

Następnie zaimplementuj klasę GrainDeactivateExtension , zapewniając implementację Deactivate metody .

Aby uzyskać dostęp do ziarna docelowego, pobierz element IGrainContext z konstruktora. Jest wstrzykiwany poprzez wstrzykiwanie zależności podczas tworzenia rozszerzenia.

public sealed class GrainDeactivateExtension : IGrainDeactivateExtension
{
    private IGrainContext _context;

    public GrainDeactivateExtension(IGrainContext context)
    {
        _context = context;
    }

    public Task Deactivate(string msg)
    {
        var reason = new DeactivationReason(DeactivationReasonCode.ApplicationRequested, msg);
        _context.Deactivate(reason);
        return Task.CompletedTask;
    }
}

Dezaktywacja rejestracji i użycia rozszerzenia

Po zdefiniowaniu interfejsu i implementacji zarejestruj rozszerzenie podczas konfigurowania silosu AddGrainExtension przy użyciu metody .

siloBuilder.AddGrainExtension<IGrainDeactivateExtension, GrainDeactivateExtension>();

Aby użyć rozszerzenia na dowolnym ziarnie, pobierz odwołanie do rozszerzenia i wywołaj jego Deactivate metodę.

var grain = client.GetGrain<SomeExampleGrain>(someKey);
var grainReferenceAsInterface = grain.AsReference<IGrainDeactivateExtension>();

await grainReferenceAsInterface.Deactivate("Because, I said so...");

Przykład rozszerzenia manipulowania stanem

W tym przykładzie pokazano dodawanie metod GetState i SetState do dowolnego ziarna przez rozszerzenia, co umożliwia manipulowanie stanem wewnętrznym ziarna.

Interfejs rozszerzenia manipulowania stanem

Najpierw zdefiniuj interfejs IGrainStateAccessor<T> zawierający metody GetState i SetState. Ponownie ten interfejs musi pochodzić z klasy IGrainExtension.

public interface IGrainStateAccessor<T> : IGrainExtension
{
    Task<T> GetState();
    Task SetState(T state);
}

Po udostępnieniu dostępu do ziarna docelowego użyj rozszerzenia, aby manipulować jego stanem. W tym przykładzie użyj rozszerzenia, aby uzyskać dostęp do określonej wartości stanu liczby całkowitej i zmodyfikować ją w ramach ziarna docelowego.

Implementacja rozszerzenia do manipulowania stanem

Używane rozszerzenie to IGrainStateAccessor<T>, udostępniając metody pobierania i ustawiania wartości stanu typu T. Aby utworzyć rozszerzenie, zaimplementuj interfejs w klasie, przyjmując element getter i setter jako argumenty w konstruktorze.

public sealed class GrainStateAccessor<T> : IGrainStateAccessor<T>
{
    private readonly Func<T> _getter;
    private readonly Action<T> _setter;

    public GrainStateAccessor(Func<T> getter, Action<T> setter)
    {
        _getter = getter;
        _setter = setter;
    }

    public Task<T> GetState()
    {
        return Task.FromResult(_getter.Invoke());
    }

    public Task SetState(T state)
    {
        _setter.Invoke(state);
        return Task.CompletedTask;
    }
}

W poprzedniej implementacji klasa GrainStateAccessor<T> przyjmuje getter i setter jako argumenty w konstruktorze. Ci delegaci odczytują i modyfikują stan ziarna docelowego. Metoda GetState() zwraca obiekt opakowujący bieżącą wartość stanu Task<TResult>, a metoda T ustawia nową wartość stanu SetState(T state).

Rejestracja i użycie rozszerzenia do manipulacji stanem

Aby użyć rozszerzenia, aby uzyskać dostęp do stanu ziarna docelowego i zmodyfikować go, zarejestruj rozszerzenie i ustaw jego składniki w metodzie ziarna Grain.OnActivateAsync() docelowego.

public override Task OnActivateAsync()
{
    // Retrieve the IGrainStateAccessor<T> extension
    var accessor = new GrainStateAccessor<int>(
        getter: () => this.Value,
        setter: value => this.Value = value);

    // Set the extension as a component of the target grain's context
    ((IGrainBase)this).GrainContext.SetComponent<IGrainStateAccessor<int>>(accessor);

    return base.OnActivateAsync();
}

W poprzednim przykładzie utwórz nowe wystąpienie GrainStateAccessor<int>, uwzględniając getter i setter dla wartości stanu liczby całkowitej. getter odczytuje właściwość Value z ziarna docelowego, natomiast setter ustawia nową wartość właściwości Value. Następnie ustaw tę instancję jako składnik kontekstu ziarna docelowego, przy użyciu metody IGrainContext.SetComponent.

Po zarejestrowaniu rozszerzenia użyj go, aby pobrać i ustawić stan ziarna docelowego, korzystając z dostępu do niego za pośrednictwem odwołania do rozszerzenia.

// Get a reference to the IGrainStateAccessor<int> extension
var accessor = grain.AsReference<IGrainStateAccessor<int>>();

// Get the current value of the state
var value = await accessor.GetState();

// Set a new value of the state
await accessor.SetState(10);

W poprzednim przykładzie uzyskaj odwołanie do rozszerzenia IGrainStateAccessor<int> dla określonej instancji ziarna, korzystając z metody GrainExtensions.AsReference. Następnie użyj tej referencji, aby wywołać metody GetState() i SetState(T state), w celu odczytania i zmodyfikowania wartości stanu docelowego ziarna.

Zobacz także