internal static IOwned <TService> CreateActivatedService(IServiceProvider?services)
            {
                if (services == null)
                {
                    throw new RpcFailureException(RpcFailure.RemoteDefinitionError, "An IServiceProvider must be supplied when services are published using IServiceProvider factories.");
                }

                TService service = services.GetService <TServiceImpl>();

                if (service != null)
                {
                    return(OwnedObject.CreateUnowned(service));
                }

                service = (TService)Factory.Value(services, Array.Empty <object>());
                return(OwnedObject.Create(service));
            }
        /// <summary>
        /// Publishes an RPC service instance with the help of a service provider factory.
        /// </summary>
        /// <typeparam name="TService">The type of the published instance.</typeparam>
        /// <param name="factory">A factory function that should create the service instance specified by the <see cref="RpcObjectId"/>
        /// with the help of the provided <see cref="IServiceProvider"/>.</param>
        /// <returns>A scoped object including the <see cref="RpcObjectRef"/> identifying the published instance. The scoped object will unpublish
        /// the service instance when disposed.</returns>
        public static IOwned <RpcObjectRef <TService> > PublishInstance <TService>(this IRpcServicePublisher servicePublisher, Func <IServiceProvider, RpcObjectId, TService> factory)
            where TService : class
        {
            if (servicePublisher is null)
            {
                throw new ArgumentNullException(nameof(servicePublisher));
            }

            IOwned <TService> CreateActivatedService(IServiceProvider?services, RpcObjectId objectId)
            {
                if (services == null)
                {
                    throw new RpcDefinitionException("An IServiceProvider must be supplied when services are published using IServiceProvider factories.");
                }

                return(OwnedObject.CreateUnowned(factory(services, objectId)));
            }

            return(servicePublisher.PublishInstance(CreateActivatedService));
        }
        public RpcObjectRef <TService> GetOrPublishInstance <TService>(TService serviceInstance) where TService : class
        {
            if (serviceInstance is null)
            {
                throw new ArgumentNullException(nameof(serviceInstance));
            }

            InstanceKey key;

            lock (this.syncRoot)
            {
                key = new InstanceKey(serviceInstance);
                if (this.serviceImplToId.TryGetValue(key, out var instanceId))
                {
                    return(new RpcObjectRef <TService>(this.connectionInfo, instanceId, this.GetPublishedServices(instanceId).ToArray()));
                }
            }

            // Not published, so we try to register the serviceInstance's service definitions
            // and then publish it.

            var allServices = RpcBuilderUtil.GetAllServices(serviceInstance.GetType(), true);

            this.TryRegisterServiceDefinitions(allServices, null);

            var connectionInfo = this.RetrieveConnectionInfo();

            lock (this.syncRoot)
            {
                // Let's try again.
                if (this.serviceImplToId.TryGetValue(key, out var instanceId))
                {
                    // Somebody beat us to it.
                    return(new RpcObjectRef <TService>(this.connectionInfo, instanceId, this.GetPublishedServices(instanceId).ToArray()));
                }

                var objectId             = RpcObjectId.NewId();
                var newPublishedServices = this.PublishInstanceCore_Locked(allServices, OwnedObject.CreateUnowned(serviceInstance), objectId, true);
                return(new RpcObjectRef <TService>(connectionInfo, objectId, newPublishedServices.ToArray()));
            }
        }
        public static IOwned <RpcSingletonRef <TService> > PublishSingleton <TService>(this IRpcServicePublisher servicePublisher, TService singletonService, bool takeOwnership = false) where TService : class
        {
            if (servicePublisher is null)
            {
                throw new ArgumentNullException(nameof(servicePublisher));
            }

            return(servicePublisher.PublishSingleton(takeOwnership ? OwnedObject.Create(singletonService) : OwnedObject.CreateUnowned(singletonService)));
        }