public void LinkGameObjectToSpatialOSEntity(EntityId entityId, GameObject gameObject,
                                                    params Type[] componentTypesToAdd)
        {
            var linkedComponent = gameObject.GetComponent <LinkedEntityComponent>();

            if (linkedComponent == null)
            {
                linkedComponent = gameObject.AddComponent <LinkedEntityComponent>();
            }
            else if (linkedComponent.IsValid)
            {
                throw new InvalidOperationException(
                          $"GameObject is already linked to the entity with ID {linkedComponent.EntityId}");
            }

            if (!entityIdToGameObjects.TryGetValue(entityId, out var linkedGameObjects))
            {
                linkedGameObjects = new List <GameObject>();
                entityIdToGameObjects.Add(entityId, linkedGameObjects);
            }

            linkedGameObjects.Add(gameObject);

            linkedComponent.IsValid  = true;
            linkedComponent.EntityId = entityId;
            linkedComponent.World    = world;
            linkedComponent.Worker   = workerSystem;
            linkedComponent.Linker   = this;

            var injectors = new List <RequiredSubscriptionsInjector>();

            foreach (var component in gameObject.GetComponents <MonoBehaviour>())
            {
                if (component == null)
                {
                    // todo consider - could also tell the user that they have a bad ref here
                    continue;
                }

                var type = component.GetType();
                if (RequiredSubscriptionsDatabase.HasRequiredSubscriptions(type) &&
                    RequiredSubscriptionsDatabase.WorkerTypeMatchesRequirements(workerSystem.WorkerType, type))
                {
                    // todo this should possibly happen when the command buffer is flushed too
                    injectors.Add(new RequiredSubscriptionsInjector(component, entityId, subscriptionSystem,
                                                                    () => lifecycleSystem.EnableMonoBehaviour(component),
                                                                    () => lifecycleSystem.DisableMonoBehaviour(component)));
                }
            }

            gameObjectToInjectors.Add(gameObject, injectors);

            if (entityId.IsValid())
            {
                AddComponentsToEntity(entityId, gameObject, componentTypesToAdd);
            }
        }
        // todo should either special case monobehaviours or not use callbacks
        // for non monobehaviours we could use functors
        public RequiredSubscriptionsInjector(object target, EntityId entityId, SubscriptionSystem subscriptionSystem,
                                             Action onEnable = null, Action onDisable = null)
        {
            info = RequiredSubscriptionsDatabase.GetOrCreateRequiredSubscriptionsInfo(target.GetType());
            if (info.RequiredTypes.Length == 0)
            {
                return;
            }

            this.target    = target;
            this.onEnable  = onEnable;
            this.onDisable = onDisable;

            subscriptions = new SubscriptionAggregate(subscriptionSystem, entityId, info.RequiredTypes);
            subscriptions.SetAvailabilityHandler(Handler.Pool.Rent(this));
        }
        // todo should either special case monobehaviours or not use callbacks
        // for non monobehaviours we could use functors
        public RequiredSubscriptionsInjector(object target, EntityId entityId, SubscriptionSystem subscriptionSystem,
                                             Action onEnable = null, Action onDisable = null)
        {
            this.target    = target;
            this.onEnable  = onEnable;
            this.onDisable = onDisable;

            info = RequiredSubscriptionsDatabase.GetOrCreateRequiredSubscriptionsInfo(target.GetType());

            if (info == null || info.RequiredTypes.Length == 0)
            {
                onEnable?.Invoke();
                return;
            }

            subscriptions = subscriptionSystem.Subscribe(entityId, info.RequiredTypes);
            subscriptions.SetAvailabilityHandler(Handler.Pool.Rent(this));
        }