Show / Hide Table of Contents

    Integration

    Note

    Before proceeding, it is recommended to first read the components document to get an understanding of how the Dependency Container system works.

    The article goes over the steps to utilize the IContainer by providing examples from IdleKit's implementation to show how custom Entities or Services can be integrated.

    1. Setup

    First, we need to prepare the classes for the IContainer by implementing the IInjectable.

    IEntity

    All entities should implement the IInjectable interface which allows them to be bound in the IContainer and their dependencies injected when they are first loaded by the IEntityLoaderService. For more information on IEntity, please check out the Entity document.

    public class Stage : IStage, IInjectable
    {
        ...
        public virtual void Inject(IResolver resolver)
        {
            _actionService = resolver.Resolve<IActionService>();
            ...
        }
    }
    

    IService

    All services should implement the IInjectable interface which allows them to be bound in the IContainer and their dependencies injected. They are bound to the IContainer as a singleton in the IInstaller during the startup process and injected into objects that need them.

    IResolver and IDataResolver

    These are specialized and cached versions of IResolver that only allow resolving of certain types of objects such as the IEntity and IStaticData to limit the access of the IResolver. Please check out the following two implementations ITypedResolvers: IEntityResolver and IDataResolver. Below is an example of an IService utilizing the IEntityResolver to fetch the IEntity in the IContainer.

    public class RewardService : IRewardService, IInjectable
    {
        protected IEntityResolver _entityResolver;
    
        public virtual void Inject(IResolver resolver)
        {
            _entityResolver = resolver.Resolve<IEntityResolver>();
            ...
        }
    
        ...
        public virtual TReward GetReward<TReward>(string id) where TReward : IReward
        {
            return _entityResolver.Resolve<TReward>(id);
        }
    }
    
    Note

    In the default IdleKit implementation, services would persist throughout the lifetime of the app.

    IAction Integration

    All actions implement the IInjectable interface that allows them to be bound in the IContainer and their dependencies injected. They are bound to the IContainer as a singleton in the IInstaller during the startup process and injected into the objects that need them. You can retrieve an instance of any IAction from the IActionService. The actions persist throughout the lifetime of the app. Below is an example of an IStateAction implementing IInjectable and having its dependencies injected.

    public class BuyGeneratorStateAction : IStateAction : IInjectable
    {
        protected ICurrencyService _currencyService;
        protected ITimerService _timerService;
    
        ...
    
        public virtual void Inject(IResolver resolver)
        {
            _currencyService = resolver.Resolve<ICurrencyService>();
            _timerService = resolver.Resolve<ITimerService>();
        }
    }
    

    2. Binding

    After the classes are prepared, they needed to be bound to the IContainer in the IInstaller.

    The following services are bound to the IContainer in IdleKit.

    public virtual void BindServices(IContainer container)
    {
        //Helper
        container.Bind<IUserSavedData>().ToInstance(new UserSavedData(USER_SAVED_DATA)).AsSingleton().Conclude();
        container.Bind<SerializedDataCache>().ToInstance(new SerializedDataCache(SERIALIZED_DATA_CACHE)).AsSingleton().Conclude();
        container.Bind<IModifierCache>().To<ModifierCache>().AsSingleton().Conclude();
        container.Bind<IActionResolver>().To<ActionResolver>().AsSingleton().Conclude();
        container.Bind<IEntityResolver>().To<EntityResolver>().AsSingleton().Conclude();
        container.Bind<IDataResolver>().To<DataResolver>().AsSingleton().Conclude();
        container.Bind<ISerializer>().ToInstance(new SimpleJsonSerializer(Application.persistentDataPath)).AsSingleton().Conclude();
        container.Bind<IProjectionCalculator>().To<ProjectionCalculator>().AsSingleton().Conclude();
    
        // ModifierFormulaParser is transient because it caches information related to the ModifierFormula that creates it
        container.Bind<IModifierFormulaParser>().To<ModifierFormulaParser>().AsTransient().Conclude();
    
        //Generator States
        container.Bind<IAutoCollectState>().To<AutoCollectState>().AsTransient().Conclude();
        container.Bind<IProduceState>().To<ProduceState>().AsTransient().Conclude();
        container.Bind<IWaitToBuyState>().To<WaitToBuyState>().AsTransient().Conclude();
        container.Bind<IWaitToCollectState>().To<WaitToCollectState>().AsTransient().Conclude();
    
        //IService
        container.Bind<ActivityTrackingService>().AsSingleton().Conclude();
        container.Bind<IActionService>().To<ActionService>().AsSingleton().Conclude();
        container.Bind<ICurrencyService>().To<CurrencyService>().AsSingleton().Conclude();
        container.Bind<IDataLoaderService>().To<DataLoaderService>().AsSingleton().Conclude();
        container.Bind<IEconomyService>().To<EconomyService>().AsSingleton().Conclude();
        container.Bind<IEntityLoaderService>().To<EntityLoaderService>().AsSingleton().Conclude();
        container.Bind<IEventService>().To<EventService>().AsSingleton().Conclude();
        container.Bind<IModifierService>().To<ModifierService>().AsSingleton().Conclude();
        container.Bind<IProjectionService>().To<ProjectionService>().AsSingleton().Conclude();
        container.Bind<IRandomService>().To<RandomService>().AsSingleton().Conclude();
        container.Bind<IRewardService>().To<RewardService>().AsSingleton().Conclude();
        container.Bind<ITagService>().To<TagService>().AsSingleton().Conclude();
        container.Bind<ITimerService>().To<TimerService>().AsSingleton().Conclude();
        container.Bind<ITrackService>().To<TrackService>().AsSingleton().Conclude();
        container.Bind<ITradeService>().To<TradeService>().AsSingleton().Conclude();
        container.Bind<SerializationService>().AsSingleton().Conclude();
    }
    

    The following actions are bound to the IContainer in IdleKit.

    public virtual void BindActions(IContainer container)
    {
        // StateActions
        container.Bind<AdvanceStageStateAction>().AsSingleton().Conclude();
        container.Bind<AscensionCompleteStateAction>().AsSingleton().Conclude();
        container.Bind<AutomateGeneratorStateAction>().AsSingleton().Conclude();
        container.Bind<BuyCollectorStateAction>().AsSingleton().Conclude();
        container.Bind<BuyGeneratorStateAction>().AsSingleton().Conclude();
        container.Bind<ClaimGoalStateAction>().AsSingleton().Conclude();
        container.Bind<ClaimMilestoneTrackRewardsStateAction>().AsSingleton().Conclude();
        container.Bind<ClaimTimedRewardStateAction>().AsSingleton().Conclude();
        container.Bind<ClaimTimedTrackRewardsStateAction>().AsSingleton().Conclude();
        container.Bind<ClaimTrackGoalStateAction>().AsSingleton().Conclude();
        container.Bind<ClaimEventRewardsStateAction>().AsSingleton().Conclude();
        container.Bind<ClearContentIdStateAction>().AsSingleton().Conclude();
        container.Bind<ClearEventsSavedDataStateAction>().AsSingleton().Conclude();
        container.Bind<CollectFromCollectorStateAction>().AsSingleton().Conclude();
        container.Bind<CollectFromGeneratorStateAction>().AsSingleton().Conclude();
        container.Bind<CompleteMilestoneTrackStateAction>().AsSingleton().Conclude();
        container.Bind<ProgressTrackStateAction>().AsSingleton().Conclude();
        container.Bind<CreateGoalStateAction>().AsSingleton().Conclude();
        container.Bind<EventEndedStateAction>().AsSingleton().Conclude();
        container.Bind<EventStartedStateAction>().AsSingleton().Conclude();
        container.Bind<GeneratorUnitTargetHitStateAction>().AsSingleton().Conclude();
        container.Bind<IncrementGeneratorUnitStateAction>().AsSingleton().Conclude();
        container.Bind<LogLastActiveTimeStateAction>().AsSingleton().Conclude();
        container.Bind<MakeExchangeStateAction>().AsSingleton().Conclude();
        container.Bind<NewContentStateAction>().AsSingleton().Conclude();
        container.Bind<NewStageStateAction>().AsSingleton().Conclude();
        container.Bind<NewUserStateAction>().AsSingleton().Conclude();
        container.Bind<ProgressGoalStateAction>().AsSingleton().Conclude();
        container.Bind<ProgressMilestoneStateAction>().AsSingleton().Conclude();
        container.Bind<ResetEntitySavedDataStateAction>().AsSingleton().Conclude();
        container.Bind<SetAvailableCurrenciesStateAction>().AsSingleton().Conclude();
        container.Bind<SetContentStateAction>().AsSingleton().Conclude();
        container.Bind<SetEventEndTimeStateAction>().AsSingleton().Conclude();
        container.Bind<SetGoalProgressStateAction>().AsSingleton().Conclude();
        container.Bind<SetMilestoneProgressStateAction>().AsSingleton().Conclude();
        container.Bind<SetMilestoneCompletionInfoStateAction>().AsSingleton().Conclude();
        container.Bind<TimedRewardInitializeStateAction>().AsSingleton().Conclude();
        container.Bind<ToggleBoostStateAction>().AsSingleton().Conclude();
        container.Bind<ToggleMilestoneStateAction>().AsSingleton().Conclude();
        container.Bind<ToggleTimedActivatableStateAction>().AsSingleton().Conclude();
        container.Bind<ToggleTimedBoostStateAction>().AsSingleton().Conclude();
        container.Bind<ToggleTrackStateAction>().AsSingleton().Conclude();
        container.Bind<ToggleAvailableStateAction>().AsSingleton().Conclude();
        container.Bind<UpgradeCurrencyStateAction>().AsSingleton().Conclude();
    
        // Actions
        container.Bind<AscensionAvailableAction>().AsSingleton().Conclude();
        container.Bind<AscensionStartAction>().AsSingleton().Conclude();
        container.Bind<AsyncLoadProgressAction>().AsSingleton().Conclude();
        container.Bind<AsyncLoadCompleteAction>().AsSingleton().Conclude();
        container.Bind<ClearContentAction>().AsSingleton().Conclude();
        container.Bind<CollectorInitializedAction>().AsSingleton().Conclude();
        container.Bind<CollectorPayoutChangedAction>().AsSingleton().Conclude();
        container.Bind<CollectorSpeedChangedAction>().AsSingleton().Conclude();
        container.Bind<CollectorStateChangedAction>().AsSingleton().Conclude();
        container.Bind<ContentInitializedAction>().AsSingleton().Conclude();
        container.Bind<CurrencyAvailableAction>().AsSingleton().Conclude();
        container.Bind<CurrencyChangedAction>().AsSingleton().Conclude();
        container.Bind<CurrencyObtainedAction>().AsSingleton().Conclude();
        container.Bind<EntityAddedAction>().AsSingleton().Conclude();
        container.Bind<EntityInitializedAction>().AsSingleton().Conclude();
        container.Bind<EntityRemovedAction>().AsSingleton().Conclude();
        container.Bind<GeneratorInitializedAction>().AsSingleton().Conclude();
        container.Bind<GeneratorPayoutChangedAction>().AsSingleton().Conclude();
        container.Bind<GeneratorSpeedChangedAction>().AsSingleton().Conclude();
        container.Bind<GeneratorStateChangedAction>().AsSingleton().Conclude();
        container.Bind<GeneratorModifierIndexChangedAction>().AsSingleton().Conclude();
        container.Bind<GoalActivatedAction>().AsSingleton().Conclude();
        container.Bind<IdleKitInitializedAction>().AsSingleton().Conclude();
        container.Bind<MilestoneClaimableAction>().AsSingleton().Conclude();
        container.Bind<ModifierRegisteredAction>().AsSingleton().Conclude();
        container.Bind<ModifierUnregisteredAction>().AsSingleton().Conclude();
        container.Bind<ModifierIndexChangedAction>().AsSingleton().Conclude();
        container.Bind<ModifierToggledAction>().AsSingleton().Conclude();
        container.Bind<OfflineProgressStartAction>().AsSingleton().Conclude();
        container.Bind<OfflineProgressEndAction>().AsSingleton().Conclude();
        container.Bind<PostSerializationAction>().AsSingleton().Conclude();
        container.Bind<PreClearContentAction>().AsSingleton().Conclude();
        container.Bind<PreSerializationAction>().AsSingleton().Conclude();
        container.Bind<RewardGrantedAction>().AsSingleton().Conclude();
        container.Bind<StageGoalSlotCompletedAction>().AsSingleton().Conclude();
        container.Bind<StageInitializedAction>().AsSingleton().Conclude();
        container.Bind<StaticDataAddedAction>().AsSingleton().Conclude();
        container.Bind<StaticDataRemovedAction>().AsSingleton().Conclude();
        container.Bind<TimedActivatableEndedAction>().AsSingleton().Conclude();
        container.Bind<TimedRewardAvailableAction>().AsSingleton().Conclude();
        container.Bind<TimedRewardStartAction>().AsSingleton().Conclude();
        container.Bind<TrackCompletedAction>().AsSingleton().Conclude();
        container.Bind<TradeAcceptedAction>().AsSingleton().Conclude();
        container.Bind<TradeDeclinedAction>().AsSingleton().Conclude();
        container.Bind<UnityFixedUpdatedAction>().AsSingleton().Conclude();
        container.Bind<UnityLateUpdatedAction>().AsSingleton().Conclude();
        container.Bind<UnityPausedAction>().AsSingleton().Conclude();
        container.Bind<UnityTerminatedAction>().AsSingleton().Conclude();
        container.Bind<UnityUpdatedAction>().AsSingleton().Conclude();
    }
    

    3. Startup

    Lastly, in the startup script (Startup.cs), the IContext is binded, which creates IContainer and calls the IInstaller.Install method. The services and actions from the previous step would be bound. After the binding is complete, the app would be ready for gameplay.

    Startup.cs

    public virtual void StartGame()
    {
        ClearLoadPhases();
    
        context.Bind();
    
        SetInitializationLoadPhases();
        SetLoadContentLoadPhases();
    
        Load(OnLoadProgress, OnLoadComplete);
    }
    

    Context.cs

    public virtual void Bind()
    {
        installer.Install(container);
    }
    

    IKInstaller.cs

    public override void Install(IContainer container)
    {
        BindLogger(container);
        BindServices(container);
        BindActions(container);
        BindLoadPhases(container);
    
        InitializeServices(container);
    }
    
    Back to top Copyright © 2020 East Side Games Inc.