### CheatSheet.md

## Installers Cheat-Sheet

Below are a bunch of randomly assorted examples of bindings that you might include in one of your installers.

For more examples, you may also be interested in reading some of the Unit tests (see `Zenject/OptionalExtras/UnitTests` and `Zenject/OptionalExtras/IntegrationTests` directories)

    // Create a new instance of Foo for every class that asks for it
    Container.Bind<Foo>().AsTransient();

    // This is equivalent since AsTransient is the default
    Container.Bind<Foo>();

    // Create a new instance of Foo for every class that asks for an IFoo
    Container.Bind<IFoo>().To<Foo>().AsTransient();

    // This is equivalent since Transient is the default
    Container.Bind<IFoo>().To<Foo>();

    // Non generic versions
    Container.Bind(typeof(IFoo)).AsTransient();
    Container.Bind(typeof(IFoo)).To(typeof(Foo)).AsTransient();

    ///////////// AsSingle

    // Create one definitive instance of Foo and re-use that for every class that asks for it
    Container.Bind<Foo>().AsSingle();

    // Create one definitive instance of Foo and re-use that for every class that asks for IFoo
    Container.Bind<IFoo>().To<Foo>().AsSingle();

    // In this example, the same instance of Foo will be used for all three cases
    Container.Bind<Foo>().AsSingle();
    Container.Bind<IFoo>().To<Foo>().AsSingle();
    Container.Bind<IFoo2>().To<Foo>().AsSingle();

    // Non generic versions
    Container.Bind(typeof(Foo)).AsSingle();
    Container.Bind(typeof(IFoo)).AsSingle(typeof(Foo));

    ///////////// BindAllInterfaces

    // Bind all interfaces that Foo implements to a new singleton of type Foo
    Container.BindAllInterfaces<Foo>().To<Foo>().AsSingle();

    // So for example if Foo implements ITickable and IInitializable then the above
    // line is equivalent to this:
    Container.Bind<ITickable>().To<Foo>().AsSingle();
    Container.Bind<IInitializable>().To<Foo>().AsSingle();

    ///////////// FromInstance

    // Use the given instance everywhere that Foo is used
    Container.Bind<Foo>().FromInstance(new Foo());

    // This is simply a shortcut for the above binding
    // This can be a bit nicer since the type argument can be deduced from the parameter
    Container.BindInstance(new Foo());

    // Note that FromInstance is different from AsSingle because it does allow multiple bindings
    // and you can't re-use the same instance in multiple bindings like you can with AsSingle
    // For example, the following is allowed and will match any constructor parameters of type List<Foo>
    // (and throw an exception for parameters that ask for a single Foo)
    Container.Bind<Foo>().FromInstance(new Foo());
    Container.Bind<Foo>().FromInstance(new Foo());

    ///////////// Binding primitive types

    // Use the number 10 every time an int is requested
    // You'd never really want to do this, you should almost always use a When condition for primitive values (see conditions section below)
    Container.Bind<int>().FromInstance(10);
    Container.Bind<bool>().FromInstance(false);

    // These are the same as above
    // This can be a bit nicer though since the type argument can be deduced from the parameter
    // Again though, be careful to use conditions to limit the scope of usage for values
    // or consider using a Settings object as described above
    Container.BindInstance(10);
    Container.BindInstance(false);

    ///////////// FromMethod

    // Create instance of Foo when requested, using the given method
    // Note that for more complex construction scenarios, you might consider using a factory
    // instead
    Container.Bind<Foo>().FromMethod(GetFoo);

    Foo GetFoo(InjectContext ctx)
    {
        return new Foo();
    }

    // Randomly return one of several different implementations of IFoo
    // We use Instantiate here instead of just new so that Foo1 gets its members injected
    Container.Bind<IFoo>().FromMethod(GetFoo);

    IFoo GetFoo(InjectContext ctx)
    {
        switch (UnityEngine.Random.Range(0, 3))
        {
            case 0:
                return ctx.Container.Instantiate<Foo1>();

            case 1:
                return ctx.Container.Instantiate<Foo2>();
        }

        return ctx.Container.Instantiate<Foo3>();
    }

    // Using lambda syntax
    Container.Bind<Foo>().FromMethod((ctx) => new Foo());

    // This is equivalent to AsTransient
    Container.Bind<Foo>().FromMethod((ctx) => ctx.Container.Instantiate<Foo>());

    ///////////// FromResolveGetter

    // Bind to a property on another dependency
    // This can be helpful to reduce coupling between classes
    Container.Bind<Foo>().AsSingle();

    Container.Bind<Bar>().FromResolveGetter<Foo>(foo => foo.GetBar());

    // Another example using values
    Container.Bind<string>().FromResolveGetter<Foo>(foo => foo.GetTitle());

    ///////////// FromGameObject (singleton)

    // Create a new game object at the root of the scene, add the Foo MonoBehaviour to it, and name it "Foo"
    Container.Bind<Foo>().FromGameObject().AsSingle();

    // You can also specify the game object name to use using WithGameObjectName
    Container.Bind<Foo>().FromGameObject().WithGameObjectName("Foo1").AsSingle();

    // Bind to an interface instead
    Container.Bind<IFoo>().To<Foo>().FromGameObject().AsSingle();

    ///////////// FromPrefab (singleton)

    // Create a new game object at the root of the scene using the given prefab
    // It is assumed that the Foo is a MonoBehaviour here and that Foo has been
    // previously added to the prefab
    // After zenject creates a new GameObject from the given prefab, it will
    // search the prefab for a component of type 'Foo' and return that
    GameObject fooPrefab;
    Container.Bind<Foo>().FromPrefab(fooPrefab).AsSingle();

    // Bind to interface instead
    Container.Bind<IFoo>().To<Foo>().FromPrefab(fooPrefab).AsSingle();

    // In this example we use AsSingle but with different components
    // Note here that only one instance of the given prefab will be
    // created.  The AsSingle applies to the prefab itself and not to
    // the type that is being returned from the prefab.
    // For this to work, there must be both a Foo MonoBehaviour and
    // a Bar MonoBehaviour somewhere on the prefab
    GameObject prefab;
    Container.Bind<Foo>().FromPrefab(prefab).AsSingle();
    Container.Bind<Bar>().FromPrefab(prefab).AsSingle();

    ///////////// FromPrefab (Transient)

    // Instantiate a new copy of 'fooPrefab' every time an instance of Foo is
    // requested by a constructor parameter, injected field, etc.
    GameObject fooPrefab = null;
    Container.Bind<Foo>().FromPrefab(fooPrefab);

    // Again, this is equivalent since AsTransient is the default
    Container.Bind<Foo>().FromPrefab(fooPrefab).AsTransient();

    // Bind to interface instead
    Container.Bind<IFoo>().To<Foo>().FromPrefab(fooPrefab);

    ///////////// Identifiers

    // Bind a globally accessible string with the name 'PlayerName'
    // Note however that a better option might be to create a Settings object and bind
    // that instead
    Container.Bind<string>().WithId("PlayerName").FromInstance("name of the player");

    // This is the equivalent of the line above, and is a bit more readable
    Container.BindInstance("name of the player").WithId("PlayerName");

    // We can also use IDs to bind multiple instances of the same type:
    Container.Bind<string>().WithId("FooA").FromInstance("foo");
    Container.Bind<string>().WithId("FooB").FromInstance("asdf");

    // Then when we inject these dependencies we have to use the same ID:
    public class Norf
    {
        [Inject(Id = "FooA")]
        string _foo;
    }

    public class Qux
    {
        [Inject(Id = "FooB")]
        string _foo;
    }

    // In this example, we bind three instances of Foo, including one without an ID
    Container.Bind<Foo>().AsCached();
    Container.Bind<Foo>().WithId("FooA").AsCached();
    Container.Bind<Foo>().WithId("FooA").AsCached();

    // When an ID is unspecified in an [Inject] field, it will use the first
    // instance
    // Bindings without IDs can therefore be used as a default and we can
    // specify IDs for specific versions of the same type
    public class Norf
    {
        [Inject]
        Foo _foo;
    }

    // Qux._foo will be the same instance as Norf._foo
    // This is because we are using AsCached rather than AsTransient
    // Note here that we don't want to use AsSingle since in that case
    // Qux._foo2 will also use the same instance
    public class Qux
    {
        [Inject]
        Foo _foo;

        [Inject(Id = "FooA")]
        Foo _foo2;
    }

    ///////////// Conditions

    // This will only allow Bar to depend on Foo
    // If we add Foo to the constructor of any other class it won't find it
    Container.Bind<Foo>().AsSingle().WhenInjectedInto<Bar>();

    // Use different implementations of IFoo dependending on which
    // class is being injected
    Container.Bind<IFoo>().To<Foo1>().AsSingle().WhenInjectedInto<Bar>();
    Container.Bind<IFoo>().To<Foo2>().AsSingle().WhenInjectedInto<Qux>();

    // Use "Foo1" as the default implementation except when injecting into
    // class Qux, in which case use Foo2
    Container.Bind<IFoo>().To<Foo1>().AsSingle();
    Container.Bind<IFoo>().To<Foo2>().AsSingle().WhenInjectedInto<Qux>();

    // Allow depending on Foo in only a few select classes
    Container.Bind<Foo>().AsSingle().WhenInjectedInto(typeof(Bar), typeof(Qux), typeof(Baz));

    // Supply "my game" for any strings that are injected into the Gui class with the identifier "Title"
    Container.BindInstance("my game").WithId("Title").WhenInjectedInto<Gui>();

    // Supply 5 for all ints that are injected into the Gui class
    Container.BindInstance(5).WhenInjectedInto<Gui>();

    // Supply 5 for all ints that are injected into a parameter or field
    // inside type Gui that is named 'width'
    // This is usually not a good idea since the name of a field can change
    // easily and break the binding but shown here as an example  :)
    Container.BindInstance(5.0f).When(ctx =>
        ctx.ObjectType == typeof(Gui) && ctx.MemberName == "width");

    // Create a new 'Foo' for every class that is created as part of the
    // construction of the 'Bar' class
    // So if Bar has a constructor parameter of type Qux, and Qux has
    // a constructor parameter of type IFoo, a new Foo will be created
    // for that case
    Container.Bind<IFoo>().To<Foo>().AsTransient().When(
        ctx => ctx.AllObjectTypes.Contains(typeof(Bar)));

    ///////////// Complex conditions example

    var foo1 = new Foo();
    var foo2 = new Foo();

    Container.Bind<Bar>().WithId("Bar1").AsTransient();
    Container.Bind<Bar>().WithId("Bar2").AsTransient();

    // Here we use the 'ParentContexts' property of inject context to sync multiple corresponding identifiers
    Container.BindInstance(foo1).When(c => c.ParentContexts.Where(x => x.MemberType == typeof(Bar) && x.Identifier == "Bar1").Any());
    Container.BindInstance(foo2).When(c => c.ParentContexts.Where(x => x.MemberType == typeof(Bar) && x.Identifier == "Bar2").Any());

    // This results in:
    // Container.Resolve<Bar>("Bar1").Foo == foo1
    // Container.Resolve<Bar>("Bar2").Foo == foo2

    ///////////// FromResolve

    // This will result in IBar, IFoo, and Foo, all being bound to the same instance of
    // Foo which is assume to exist somewhere on the given prefab
    GameObject fooPrefab;
    Container.Bind<Foo>().FromPrefab(fooPrefab).AsSingle();
    Container.Bind<IBar>().To<Foo>().FromResolve();
    Container.Bind<IFoo>().To<IBar>().FromResolve();

    // This will result in the same behaviour as the above
    GameObject fooPrefab = null;
    Container.Bind<Foo>().FromPrefab(fooPrefab).AsSingle();
    Container.Bind<IBar>().To<Foo>().FromPrefab(fooPrefab).AsSingle();
    Container.Bind<IFoo>().To<Foo>().FromPrefab(fooPrefab).AsSingle();

    ///////////// Rebind

    // Rebind can be used to override previous bindings
    // This will result in IFoo being bound to only Bar
    // The binding to Foo will have been removed
    // Normally the order that the bindings occur in doesn't
    // matter at all, but Rebind does create an order-dependency
    // so use with caution
    Container.Bind<IFoo>().To<Foo>().AsSingle();
    Container.Rebind<IFoo>().To<Bar>().AsSingle();

    ///////////// Installing Other Installers

    // Immediately call InstallBindings() on FooInstaller
    FooInstaller.Install(Container);

    // Before calling FooInstaller, configure a property of it
    Container.BindInstance("foo").WhenInjectedInto<FooInstaller>();
    FooInstaller.Install(Container);

    // We can also pass arguments directly
    // This line is equivalent to the above two lines
    FooInstaller.Install(Container, new object[] { "foo" });

    // After calling FooInstaller, override one of its bindings
    // We assume here that FooInstaller binds IFoo to something
    FooInstaller.Install(Container);
    Container.Rebind<IFoo>().To<Bar>().AsSingle();

    ///////////// Manual Use of Container

    // This will fill in any parameters marked as [Inject] and also call any [Inject] methods
    var foo = new Foo();
    Container.Inject(foo);

    // Return an instance for IFoo, using the bindings that have been added previously
    // Internally it is what is triggered when you fill in a constructor parameter of type IFoo
    // Note: It will throw an exception if it cannot find a match
    Container.Resolve<IFoo>();

    // Same as the above except returns null when it can't find the given type
    Container.TryResolve<IFoo>();

    // Return a list of 2 instances of type Foo
    Container.BindInstance(new Foo());
    Container.BindInstance(new Foo());
    var foos = Container.ResolveAll<IFoo>();

    // Create a new instance of Foo and inject on any of its members
    // And fill in any constructor parameters Foo might have
    Container.Instantiate<Foo>();

    GameObject prefab = null;
    // Instantiate a new prefab and have any injectables filled in on the prefab
    GameObject go = Container.InstantiatePrefab(prefab);

    // Instantiate a new prefab and return a specific monobehaviour
    Foo foo2 = Container.InstantiatePrefabForComponent<Foo>(prefab);

    // Add a new component to an existing game object
    Foo foo3 = Container.InstantiateComponent<Foo>(gameObject);