v0.36.0 [MetaServiceContract] server-side contract APIs, framework subscribers removed
[MetaServiceContract] — server code addresses a service by contract
Framework subscriber interfaces are gone as a mechanism. ILobbySubscriber becomes
ILobbyListener: an ordinary contract a meta service inherits, whose methods are ordinary meta
methods with real ids, dispatcher cases and client-side replay.
Mark a contract [MetaServiceContract] and the generator emits an awaitable mirror into the
contract's own assembly — which is what lets code that cannot reference the game make a typed call:
[MetaServiceContract]
public interface ILobbyListener { void OnMatchFound(MatchFoundEvent e); }
// generated beside it: Task OnMatchFoundAsync(string entityId, MatchFoundEvent e)
[MetaService(StateType = typeof(ProfileState))]
public interface IProfileService : IMetaService, ILobbyListener { }
public partial class ProfileService : IProfileService
{
[MetaMethod(Alias = "OnMatchFound", Mode = ExecutionMode.Server, GenerateClientApi = false)]
public void OnMatchFound(MatchFoundEvent e) => State.CurrentGameId = e.MatchId;
}
// framework side — inject once, entity id per call
public LobbyGrain(ILogger<LobbyGrain> logger, ILobbyListenerServerApi? players = null) { ... }
await _players.OnMatchFoundAsync(entityId, evt);
The entity id is an argument, not a binding, so one injected instance serves every target. Delivery
is a normal dispatch — state, broadcast, persistence, client replay — is awaited, so a
target-side failure reaches the caller, and works on a cold entity, so an offline player finds the
result waiting on next subscribe.