Поделиться через


Расширения зерна

Расширения зерна предоставляют способ добавления дополнительного поведения к зернам. Расширяя зерно с интерфейсом, производным от IGrainExtension, можно добавить новые методы и функциональные возможности к зерне.

В этой статье вы увидите два примера расширений зерна. В первом примере показано, как добавить Deactivate метод ко всем зернам, которые можно использовать для деактивации зерна. Во втором примере показано, как добавить GetState и SetState метод к любому зерне, что позволяет управлять внутренним состоянием зерна.

Пример деактивации расширения

В этом примере вы узнаете, как автоматически добавить Deactivate метод ко всем зернам. Этот метод можно использовать для деактивации зерна и принятия строки в качестве параметра сообщения. Orleans зерна уже поддерживают эту функцию через IGrainManagementExtension интерфейс. Тем не менее, в этом примере показано, как можно добавить эту или аналогичную функциональность самостоятельно.

Деактивация интерфейса расширения

Сначала определите IGrainDeactivateExtension интерфейс, содержащий Deactivate метод. Интерфейс должен быть производным от IGrainExtension.

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

Деактивация реализации расширения

Затем реализуйте GrainDeactivateExtension класс, который предоставляет реализацию для Deactivate метода.

Чтобы получить доступ к целевому зерню, извлекается IGrainContext из конструктора. Он внедряется при создании расширения с внедрением зависимостей.

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;
    }
}

Отключение регистрации и использования расширений

Теперь, когда вы определили интерфейс и реализацию, зарегистрируйте расширение при настройке сило с AddGrainExtension помощью метода.

siloBuilder.AddGrainExtension<IGrainDeactivateExtension, GrainDeactivateExtension>();

Чтобы использовать расширение для любого зерна, получите ссылку на расширение и вызовите Deactivate метод.

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

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

Пример расширения управления состоянием

В этом примере вы узнаете, как добавить GetState и SetState метод к любому зерне через расширения, что позволяет управлять внутренним состоянием зерна.

Интерфейс расширения управления состоянием

Сначала определите IGrainStateAccessor<T> интерфейс, содержащий GetState и SetState методы. Опять же, этот интерфейс должен быть производным от IGrainExtension.

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

Получив доступ к целевому зерню, вы можете использовать расширение для управления его состоянием. В этом примере вы используете расширение для доступа и изменения определенного целочисленного значения состояния в целевом зерне.

Реализация расширения управления состоянием

Используется IGrainStateAccessor<T>расширение, которое предоставляет методы для получения и задания значения состояния типа T. Чтобы создать расширение, вы реализуете интерфейс в классе, который принимает и getter в setter качестве аргументов в его конструкторе.

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;
    }
}

В предыдущей реализации GrainStateAccessor<T> класс принимает getter и setter аргументы в конструкторе. Эти делегаты используются для чтения и изменения состояния целевого зерна. Метод GetState() возвращает текущее значение T состояния, а SetState(T state) метод задает Task<TResult> новое значение T состояния.

Регистрация и использование расширения управления состоянием

Чтобы использовать расширение для доступа и изменения состояния целевого зерна, необходимо зарегистрировать расширение и задать его компоненты в Grain.OnActivateAsync() методе целевого зерна.

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();
}

В приведенном выше примере создается новый экземпляр GrainStateAccessor<int> , который принимает getter значение и setter целочисленное значение состояния. Объект getter считывает Value свойство целевого зерна, а setter задает новое значение Value свойства. Затем этот экземпляр устанавливается в качестве компонента контекста целевого зерна с помощью IGrainContext.SetComponent метода.

После регистрации расширения его можно использовать для получения и задания состояния целевого зерна путем доступа к нему через ссылку на расширение.

// 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);

В предыдущем примере вы получите ссылку на IGrainStateAccessor<int> расширение для конкретного экземпляра зерна с помощью GrainExtensions.AsReference метода. Затем эту ссылку можно использовать для вызова GetState() и SetState(T state) методов для чтения и изменения значения состояния целевого зерна.

См. также