粒度扩展提供了向粒度添加额外行为的方法。 通过使用派生自 IGrainExtension的接口扩展粒度,可以将新的方法和功能添加到粒度中。
本文介绍了两个粒度扩展的示例。 第一个示例演示如何向所有的 Grain 添加一个 Deactivate
方法,该方法可用于停用这些 Grain。 第二个示例演示如何向任何Grain添加 GetState
和 SetState
方法,从而允许操作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...");
状态操控扩展示例
此示例演示如何通过扩展向任何粒子添加 GetState
和 SetState
方法,从而允许操作该粒子的内部状态。
状态操作扩展接口
首先,定义 IGrainStateAccessor<T>
包含 GetState
和 SetState
方法的接口。 同样,此接口必须派生自 IGrainExtension
。
public interface IGrainStateAccessor<T> : IGrainExtension
{
Task<T> GetState();
Task SetState(T state);
}
访问目标粒度后,可以使用扩展工具来调整其状态。 在此示例中,使用扩展访问和修改目标粒度中的特定整数状态值。
状态操作扩展的实现
使用的扩展是 IGrainStateAccessor<T>
,提供用于获取和设置类型 T
状态值的方法。 若要创建扩展,请在采用其构造函数中的 a 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
状态当前值的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();
}
在前面的示例中,创建一个新实例,利用 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);
在前面的示例中,使用GrainExtensions.AsReference方法以获取特定粒实例的IGrainStateAccessor<int>
扩展的引用。 然后,使用此引用调用 GetState()
和 SetState(T state)
方法来读取和修改目标粒度的状态值。