Skip to content

Injectable

Magicolo edited this page Jan 31, 2019 · 12 revisions

Content


Description

An injectable is an encapsulation of a subset of the world operations that can guarantee a certain usage of those operations. They are automatically injected in a system's public fields and are used for thread safety analysis. Using the most specific injectables in systems, allows thread safety analysis to be most useful to prevent data races.


Usage

using Entia;
using Entia.Injectables;
using Entia.Queryables;
using Entia.Systems;

namespace Components
{
    public struct Invincibility : IComponent { public float Time; }
    public struct Health : IComponent { public float Current, Maximum; }
}

namespace Messages
{
    public struct DoDamage : IMessage { public float Amount; }
    public struct OnDeath : IMessage { }
}

namespace Resources
{
    public struct Game : IResource
    {
        public bool WillQuit;
        public bool IsPaused;
    }
}

namespace Systems
{
    // A system that is not registered to any execution system interface.
    public struct Kill : ISystem
    {
        // There are many implemented injectables. These are some of them.
        // See the 'Entia.Injectables' namespace to discover all of them.
        public readonly Components<Components.Health> Healths;
        // Notice that more specific injectables may be nested inside a more 
        // general one.
        public readonly Components<Components.Invincibility>.Read Invincibilities;
        public readonly Receiver<Messages.DoDamage> DoDamage;
        public readonly Emitter<Messages.OnDeath> OnDeath;
        public readonly Resource<Resources.Game>.Read Game;
        public readonly Group<Read<Components.Health>> Group;
        // The world is a valid injectable but will prevent thread safety analysis
        // since is statically unpredictable.
        public readonly World World;
    }
}

Extensibility

It is possible to define how an injectable should be constructed by specifying a default implementation of an Injector<T> and linking it using the generic interface IInjectable<T>.

using System.Reflection;
using Entia;
using Entia.Core;
using Entia.Injectables;
using Entia.Injectors;
using Entia.Modules;

namespace Injectables
{
    // An injectable that gives only access to destroy operations.
    public readonly struct Destroyer : IInjectable<Injectors.Destroyer>
    {
        readonly Entities _entities;

        public Destroyer(Entities entities) { _entities = entities; }

        public bool Destroy(Entity entity) => _entities.Destroy(entity);
        public bool DestroyAll() => _entities.Clear();
    }
}

namespace Injectors
{
    public sealed class Destroyer : Injector<Injectables.Destroyer>
    {
        public override Result<Injectables.Destroyer> Inject(
            MemberInfo member,
            World world) =>
            new Injectables.Destroyer(world.Entities());
    }
}

Related