Search code examples
azureactorazure-service-fabricservice-fabric-actor

Is it normal to return actor's proxy from service


I have some service which accepts some data and then, as I think, should return an actor initialized with some values.

public class MyService : StatefulService, IMyService
{
    public IMyActor DoThings(Data data)
    {
        var actor = ActorProxy.Create<IMyActor>(new ActorId(Guid.NewGuid()));  
        actor.Init(data);
        //some other things
        return actor;
    }
}

Another service would do this:

var service = ServiceProxy.Create<ICommandBrokerService>(new Uri("fabric:/App"), ServicePartitionKey.Singleton);
var actor = service.DoThings(data);
var state = actor.GetState();
//...

So, is it okay to return an actor in such a way, or should I return actor's id and request a proxy on a call sight?

UPD: According to a @LoekD 's answer I did a wrapper to be a little type-safety.

[DataContract(Name = "ActorReferenceOf{0}Wrapper")]
public class ActorReferenceWrapper<T>
{
    [DataMember]
    public ActorReference ActorReference { get; private set; }
    public ActorReferenceWrapper(ActorReference actorRef)
    {
        ActorReference = actorRef ?? throw new ArgumentNullException();
    }

    public T Bind()
    {
        return (T)ActorReference.Bind(typeof(T));
    }

    public IActorService GetActorService(IActorProxyFactory serviceProxy=null)
    {
        return ActorReference.GetActorService(serviceProxy);
    }

    public TService GetActorService<TService>(IActorProxyFactory serviceProxyFactory) where TService : IActorService
    {
       return serviceProxyFactory.CreateActorServiceProxy<TService>(ActorReference.ServiceUri,
                ActorReference.ActorId);
    }

    public static implicit operator ActorReference(ActorReferenceWrapper<T> actorRef)
    {
        return actorRef.ActorReference;
    }

    public static explicit operator ActorReferenceWrapper<T>(ActorReference actorReference)
    {
        return new ActorReferenceWrapper<T>(actorReference);
    }
}

Solution

  • No, the types used in SF remoting must be DataContractSerializable. The contracts you use can only have fields and properties, no methods.

    So, instead of returning the proxy, return an Actor Reference.

    Next, use Bind to create a proxy from it.