粒度扩展

粒度扩展提供了向粒度添加额外行为的方法。 通过使用派生自 IGrainExtension的接口扩展粒度,可以将新的方法和功能添加到粒度中。

本文介绍了两个粒度扩展的示例。 第一个示例演示如何向所有的 Grain 添加一个 Deactivate 方法,该方法可用于停用这些 Grain。 第二个示例演示如何向任何Grain添加 GetStateSetState 方法,从而允许操作Grain的内部状态。

停用插件示例

此示例演示如何自动向所有粒度添加方法 Deactivate 。 使用该方法停用粒度;它接受字符串作为消息参数。 Orleans grains 已通过 IGrainManagementExtension 接口支持此功能。 不过,此示例演示了如何添加此功能或类似功能。

停用扩展接口

首先定义一个包含 Deactivate 方法的 IGrainDeactivateExtension 接口。 接口必须派生自 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方法配置silo时注册扩展。

siloBuilder.AddGrainExtension<IGrainDeactivateExtension, GrainDeactivateExtension>();

若要在任何粒度上使用扩展,请检索对扩展的引用并调用其 Deactivate 方法。

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

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

状态操控扩展示例

此示例演示如何通过扩展向任何粒子添加 GetStateSetState 方法,从而允许操作该粒子的内部状态。

状态操作扩展接口

首先,定义 IGrainStateAccessor<T> 包含 GetStateSetState 方法的接口。 同样,此接口必须派生自 IGrainExtension

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

访问目标粒度后,可以使用扩展工具来调整其状态。 在此示例中,使用扩展访问和修改目标粒度中的特定整数状态值。

状态操作扩展的实现

使用的扩展是 IGrainStateAccessor<T>,提供用于获取和设置类型 T状态值的方法。 若要创建扩展,请在采用其构造函数中的 a gettersetter 作为参数的类中实现接口。

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> 类在其构造函数中采用 gettersetter 自变量。 这些委托读取和修改目标粒度的状态。 GetState()方法返回封装T状态当前值的Task<TResult>,而SetState(T state)方法设置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();
}

在前面的示例中,创建一个新实例,利用 gettersetter 来设定一个整数状态值。 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);

在前面的示例中,使用GrainExtensions.AsReference方法以获取特定粒实例的IGrainStateAccessor<int>扩展的引用。 然后,使用此引用调用 GetState()SetState(T state) 方法来读取和修改目标粒度的状态值。

另请参阅