public AgentProcessTicket(
            IAgentProcessManager agentProcessManager,
            ClientSessionUri clientSessionUri,
            IMessageService messageService,
            Action disconnectedHandler)
        {
            if (agentProcessManager == null)
            {
                throw new ArgumentNullException(nameof(agentProcessManager));
            }

            if (clientSessionUri == null)
            {
                throw new ArgumentNullException(nameof(clientSessionUri));
            }

            if (disconnectedHandler == null)
            {
                throw new ArgumentNullException(nameof(disconnectedHandler));
            }

            AgentProcessManager = agentProcessManager;
            ClientSessionUri    = clientSessionUri;
            MessageService      = messageService;

            this.disconnectedHandler = disconnectedHandler;

            Id = Interlocked.Increment(ref lastId);
        }
        WorkbookAppInstallation(
            string id,
            string flavor,
            string icon,
            string [] optionalFeatures,
            Sdk sdk,
            string appPath,
            string appManagerAssembly,
            int order)
        {
            Id = id ?? throw new ArgumentNullException(nameof(id));

            Flavor = flavor
                     ?? throw new ArgumentNullException(nameof(flavor));

            Icon = icon;

            OptionalFeatures = optionalFeatures ?? Array.Empty <string> ();

            Sdk = sdk
                  ?? throw new ArgumentNullException(nameof(sdk));

            AppPath = appPath
                      ?? throw new ArgumentNullException(nameof(appPath));

            this.order = order;

            if (appManagerAssembly == null)
            {
                RegisterDefaultProcessManagers();
            }
            else
            {
                RegisterProcessManagers(Assembly.LoadFrom(appManagerAssembly));
            }

            var processManagerType = processManagers
                                     .FirstOrDefault(r => r.WorkbookAppId == Id)
                                     ?.ProcessManagerType;

            if (processManagerType == null)
            {
                throw new Exception(
                          $"No {nameof (AgentProcessManager)} registered for workbook app ID '{Id}'");
            }

            try {
                processManager = (IAgentProcessManager)Activator.CreateInstance(
                    processManagerType,
                    this);
            } catch (Exception e) {
                throw new Exception(
                          $"Unable to instantiate {processManagerType.FullName} " +
                          $"for workbook app ID '{Id}'",
                          e);
            }
        }
        public WebAssemblyAgentTicket(
            IAgentProcessManager processManager,
            IMessageService messageService,
            Action disconnectedHandler)
        {
            // WASM doesn't currently use these, but we may someday.
            this.processManager      = processManager;
            this.disconnectedHandler = disconnectedHandler;
            this.messageService      = messageService;

            client = new WebAssemblyAgentClient();
        }
        public AgentProcessTicket(
            IAgentProcessManager agentProcessManager,
            IMessageService messageService,
            Action disconnectedHandler)
        {
            AgentProcessManager = agentProcessManager
                                  ?? throw new ArgumentNullException(nameof(agentProcessManager));

            MessageService = messageService
                             ?? throw new ArgumentNullException(nameof(disconnectedHandler));

            this.disconnectedHandler = disconnectedHandler;

            Id = Interlocked.Increment(ref lastId);
        }
        WorkbookAppInstallation(
            string id,
            string flavor,
            string icon,
            string [] optionalFeatures,
            Sdk sdk,
            string appPath,
            string appManagerAssembly,
            string ticketProviderAssembly,
            int order)
        {
            Id = id ?? throw new ArgumentNullException(nameof(id));

            Flavor = flavor
                     ?? throw new ArgumentNullException(nameof(flavor));

            Icon = icon;

            OptionalFeatures = optionalFeatures ?? Array.Empty <string> ();

            Sdk = sdk
                  ?? throw new ArgumentNullException(nameof(sdk));

            AppPath = appPath
                      ?? throw new ArgumentNullException(nameof(appPath));

            this.order = order;

            if (appManagerAssembly == null)
            {
                RegisterDefaultProcessManagers();
            }
            else
            {
                RegisterProcessManagers(Assembly.LoadFrom(appManagerAssembly));
            }

            if (ticketProviderAssembly == null)
            {
                RegisterDefaultTicketProviders();
            }
            else
            {
                RegisterTicketProviders(Assembly.LoadFrom(ticketProviderAssembly));
            }

            var processType = processManagers
                              .FirstOrDefault(r => r.WorkbookAppId == Id)
                              ?.ProcessType;

            if (processType == null)
            {
                throw new Exception(
                          $"No {nameof (IAgentProcess)} registered for workbook app ID '{Id}'");
            }

            try {
                processManager = new AgentProcessManager(this, processType);
            } catch (Exception e) {
                throw new Exception(
                          $"Unable to instantiate AgentProcessManager with {processType.FullName} " +
                          $"for workbook app ID '{Id}'",
                          e);
            }

            ticketType = ticketProviders
                         .FirstOrDefault(r => r.WorkbookAppId == Id)
                         ?.TicketType;

            if (ticketType != null && !typeof(IAgentTicket).IsAssignableFrom(ticketType))
            {
                throw new Exception(
                          $"Workbook app with ID {Id} registered invalid ticket type, ticket type must be " +
                          $"assignable to IAgentTicket"
                          );
            }
        }