using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; #nullable enable namespace Capnp.Rpc { /// /// Combines multiple skeletons to represent objects which implement multiple interfaces. /// public class PolySkeleton: Skeleton { readonly Dictionary _ifmap = new Dictionary(); /// /// Adds a skeleton to this instance. /// /// Interface ID /// Skeleton to add /// is null. /// A skeleton with was already added. public void AddInterface(ulong interfaceId, Skeleton skeleton) { if (skeleton == null) throw new ArgumentNullException(nameof(skeleton)); skeleton.Claim(); _ifmap.Add(interfaceId, skeleton); } internal void AddInterface(Skeleton skeleton) { AddInterface(((IMonoSkeleton)skeleton).InterfaceId, skeleton); } /// /// Calls an interface method of this capability. /// /// ID of interface to call /// ID of method to call /// Method arguments ("params struct") /// Cancellation token, indicating when the call should cancelled. /// A Task which will resolve to the call result public override Task Invoke(ulong interfaceId, ushort methodId, DeserializerState args, CancellationToken cancellationToken = default) { if (_ifmap.TryGetValue(interfaceId, out var skel)) return skel.Invoke(interfaceId, methodId, args, cancellationToken); throw new NotImplementedException("Unknown interface id"); } /// /// Dispose pattern implementation /// protected override void Dispose(bool disposing) { foreach (var cap in _ifmap.Values) { cap.Relinquish(); } base.Dispose(disposing); } internal override void Bind(object impl) { foreach (Skeleton skel in _ifmap.Values) { skel.Bind(impl); } } } } #nullable restore