Ler en inglés

Compartir por


Extensiones de detalle

Las extensiones de detalle proporcionan una manera de agregar un comportamiento adicional a los detalles. Al ampliar un detalle con una interfaz que deriva de IGrainExtension, puede agregar nuevos métodos y funcionalidades al detalle.

En este artículo, verá dos ejemplos de extensiones de detalle. En el primer ejemplo se muestra cómo agregar un método Deactivate a todos los detalles que se pueden usar para desactivar el detalle. En el segundo ejemplo se muestra cómo agregar un método GetState y SetState a cualquier detalle, lo que le permite manipular el estado interno del detalle.

Ejemplo de desactivación de la extensión

En este ejemplo, aprenderá a agregar un método Deactivate a todos los detalles automáticamente. El método se puede usar para desactivar el detalle y acepta una cadena como un parámetro de mensaje. Los detalles Orleans ya admiten esta funcionalidad a través de la interfaz IGrainManagementExtension. Sin embargo, este ejemplo sirve para mostrar cómo puede agregar esta funcionalidad o una similar usted mismo.

Desactivación de la interfaz de extensión

Empiece por definir una interfaz IGrainDeactivateExtension, que contiene el método Deactivate. La interfaz debe derivar de IGrainExtension.

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

Desactivación de la implementación de la extensión

A continuación, implemente la clase GrainDeactivateExtension, que proporciona la implementación del método Deactivate.

Para acceder al detalle de destino, recupere el elemento IGrainContext del constructor. Se inserta al crear la extensión con inserción de dependencias.

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

Desactivación del uso y el registro de extensiones

Ahora que ha definido la interfaz y la implementación, registre la extensión al configurar el silo con el método AddGrainExtension.

C#
siloBuilder.AddGrainExtension<IGrainDeactivateExtension, GrainDeactivateExtension>();

Para usar la extensión en cualquier detalle, recupere una referencia a la extensión y llame al método Deactivate.

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

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

Ejemplo de extensión de manipulación de estado

En este ejemplo, aprenderá a agregar un método GetState y SetState a cualquier detalle a través de extensiones, lo que le permite manipular el estado interno del detalle.

Interfaz de extensión de manipulación de estado

En primer lugar, defina la interfaz IGrainStateAccessor<T>, que contiene los métodos GetState y SetState. De nuevo, esta interfaz debe derivar de IGrainExtension.

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

Una vez que acceda al detalle de destino, puede usar la extensión para manipular su estado. En este ejemplo, se usa una extensión para acceder a un valor de estado entero específico y modificarlo dentro del detalle de destino.

Implementación de la extensión de manipulación de estado

La extensión que se usa es IGrainStateAccessor<T>, que proporciona métodos para obtener y establecer un valor de estado de tipo T. Para crear la extensión, implemente la interfaz en una clase que adopta getter y setter como argumentos en su constructor.

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

En la implementación anterior, la clase GrainStateAccessor<T> adopta los argumentos getter y setter en su constructor. Estos delegados se usan para leer y modificar el estado del detalle de destino. El método GetState() devuelve un elemento Task<TResult> que encapsula el valor actual del estado T, mientras que el método SetState(T state) establece el nuevo valor del estado T.

Registro y uso de extensiones de manipulación de estado

Para usar la extensión para acceder al estado del detalle de destino y modificarlo, debe registrar la extensión y establecer sus componentes en el método Grain.OnActivateAsync() del detalle de destino.

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

En el ejemplo anterior, se crea una instancia de GrainStateAccessor<int> que adopta getter y setter para un valor de estado entero. getter lee la propiedad Value del detalle de destino, mientras que setter establece el nuevo valor de la propiedad Value. A continuación, establezca esta instancia como un componente del contexto del detalle de destino mediante el método IGrainContext.SetComponent.

Una vez registrada la extensión, puede usarla para obtener y establecer el estado del detalle de destino accediendo a él a través de una referencia a la extensión.

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

En el ejemplo anterior, obtiene una referencia a la extensión IGrainStateAccessor<int> para una instancia específica de detalle mediante el método GrainExtensions.AsReference. A continuación, puede usar esta referencia para llamar a los métodos GetState() y SetState(T state) para leer y modificar el valor de estado del detalle de destino.

Consulte también