4

I'm building an application, where I have multiple different actor types that have the same kind of behavior (CRUD) in respect to some different data objects. In order to more easily create code that handles this I've tried to create an interface, that these actors can implement.

This means that i have an actor interface that looks something like this:

public interface IMyActor1 :
    IActor,
    IDataActor<DataItem1>,
    IDataActor<DataItem2>

Where the IDataActor<T> looks like this:

public interface IDataActor<T> where T : IDataItem
{
    Task Create(T item);
    Task<T> Read(string itemId);
    Task Update(T item);
    Task Delete(string itemId);
}

And the actor it self looks like this

class MyActor1: Actor, IMyActor1
{
    ...
}

Originally i tried having IDataActor<T> derive from IActor, but understandably this isn't allowed, and i get an "Generic interfaces cannot be remoted." error when i try to deploy, so i tried this.

When I build the project now I get the following error log:

System.ArgumentException: The actor type 'MyProject.ActorProject.MyActor1' does not implement any actor interfaces. An actor interface is the one that derives from 'Microsoft.ServiceFabric.Actors.IActor' type.
  Parameter name: actorType
     at Microsoft.ServiceFabric.Actors.Runtime.ActorTypeInformation.Get(Type actorType)
     at FabActUtil.Tool.LoadActors(Assembly inputAssembly, IList`1 actorFilters, IList`1 actorTypes)
     at FabActUtil.Tool.LoadActors(ToolContext context)
     at FabActUtil.Tool.ProcessInput(ToolContext context)
     at FabActUtil.Tool.Run(ToolArguments arguments)
     at FabActUtil.Program.Main(String[] args)

The error claims that MyActor1 does not implement any actor interfaces, however it clearly does. Does anyone know is this is a bug, or if there's a practical workaround? Getting this working could save me a lot of duplicated code.

Thanks!

Kristoffer la Cour
  • 2,591
  • 3
  • 25
  • 36
  • I ran into this problem myself, but then realized that I wasn't really getting any benefit by having the interface inheritance. My suggestion would be to extract your interfaces and classes into non-actor types and use those. Just my two cents. – Chris Missal May 02 '16 at 14:02
  • This seems like a major flaw / oversight. I literally just asked this same question. – Tony May 02 '16 at 15:30

1 Answers1

2

Service Fabric currently doesn't support generic service/actor interfaces. The second error you're seeing is because it also filters out interfaces that inherit from interfaces that don't inherit from IActor (such as your IDataActor<T>). The error message could be improved there.

To work around this limitation for services, I've used Castle DynamicProxy (the code is too long and complex for a SO answer; I may write it up in a blog post when I get the time).

That said, I think you may want to consider that actors should encapsulate more than just data. You should be exposing operations that represent behavior. Otherwise that would most probably result in high coupling, degraded maintainability, repeated code, etc. – which kind of defeats the purpose of microservices.

Eli Arbel
  • 22,391
  • 3
  • 45
  • 71
  • Answer supported by this answer from a Senior Microsoft Engineer. http://stackoverflow.com/questions/36985580/service-fabric-with-generic-services/36992513 – Tony May 03 '16 at 14:15
  • The actors does more than store data, this is a simplified scenario. But thanks, I read Tony's question and the answers, and it seems i'll have to think of something else. – Kristoffer la Cour May 04 '16 at 08:09