繁体   English   中英

使用 Orleans 实现相同粒度接口的多个实现

[英]Multiple implementations of same grain interface using Orleans

我有一个具有以下结构的奥尔良应用程序:

public interface IGraintest : Orleans.IGrainWithGuidCompoundKey
{
    Task Init();
}



public abstract class GraintestImpl<T> : Grain, IGraintest, Deserializer<T>
{
    string streamName;
    public Task Init()
    {
        return Task.CompletedTask;
    }


    public override async Task OnActivateAsync()
    {
        var primaryKey = this.GetPrimaryKey(out streamName);
        var streamProvider = GetStreamProvider("SMSProvider");
        var stream = streamProvider.GetStream<String>(primaryKey, streamName);

        // To resume stream in case of stream deactivation
        var subscriptionHandles = await stream.GetAllSubscriptionHandles();

        if (subscriptionHandles.Count > 0)
        {
            foreach (var subscriptionHandle in subscriptionHandles)
            {
                await subscriptionHandle.ResumeAsync(OnNextMessage);
            }
        }

        await stream.SubscribeAsync(OnNextMessage);
    }

    public abstract T Process(string l);

    private Task OnNextMessage(string message, StreamSequenceToken sequenceToken)
    {
        T obj = Process(message);
        //gonna do something with obj here
        return Task.CompletedTask;
    }
}
public class ProcessImplA: GraintestImpl<Car>
{
    public override Car Process(string l)
    {
        return new Car(l);  
    }
}
public class ProcessImplB: GraintestImpl<Boat>
{
    public override Boat Process(string l)
    {
        return new Boat(l);
    }
}

这里我有一个 grain,我用它来从流中读取消息并对它们应用一些操作。 由于我想使用不同的对象类型,因此我创建了一个抽象类来实现该接口。 问题出在这里:

var sourceOne = client.GetGrain<IGraintest>(guid, "Car");
var sourceTwo = client.GetGrain<IGraintest>(guid, "Boat");

当我像这样运行程序时,我得到错误代码:

Exception while trying to run client: Cannot resolve grain interface ID=-<blabla> to a grain class because of multiple implementations of it

所以我的问题是,我可以做一个小改动来完成这项工作,还是我必须为我想使用的每个 ProcessImpl grain 创建一个 grain 接口?

您可以使用接受 grain 类名称前缀的重载来消除GetGrain调用的歧义。

var sourceOne = client.GetGrain<IGraintest>(guid, "Car", grainClassNamePrefix: "MyNamespace.ProcessImplA");
var sourceTwo = client.GetGrain<IGraintest>(guid, "Boat", grainClassNamePrefix: "MyNamespace.ProcessImplB");

否则,如果接口有两个实现,那么运行时将不知道如何决定使用哪一个。 对于您的情况重要的是, IGrainFactory实现不知道有关哪个类实现哪个构造的通用接口的信息,因此它无法选择实现。

另一种方法是为你的谷物类添加一个标记接口,例如,你可以有IGrainTestImplBoat

public interface IGrainTestImplBoat : Orleans.IGrainWithGuidCompoundKey { }

public class ProcessImplB : GraintestImpl<Boat>, IGrainTestImplBoat { /* ... */ }

var sourceTwo = client.GetGrain<IGrainTestImplBoat>(guid, "Boat");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM