Zenject: Binding

yoonsang lee·2022년 5월 29일
0

Binding

All DI frameworks just provide binding functionality of the type to the target instance.
This works with Container in every Installers in Zenject.

repo

when the container is asked to construct the actual instance of a given type

  1. it queries the list of construct arguments using C# reflection, and all fields/properties marked with an [Inject] attribute.

  2. therefore, it attempts to resolve each requirements, which call the ctor and create the new instance.

public class Foo {
    IBar _bar;

    public Foo(IBar bar) {
        _bar = bar;
    }
}

// bind code is as like this below
Container.Bind<Foo>().AsSingle();
Container.Bind<IBar>().To<Bar>().AsSingle();
  • This means every class that requires a dependency of type Foo use the same instance, which it will automatically create when needed (lazy).

  • any class that requires the IBar interface (like Foo) will be given the same instance of type Bar.


Basic Structure of Binding

Container.Bind<ContractType>()
    .WithId(Identifier)
    .To<ResultType>()
    .FromConstructionMethod()
    .AsScope()
    .WithArguments(Arguments)
    .OnInstantiated(InstantiatedCallback)
    .When(Condition)
    .(Copy|Move)Into(All|Direct)SubContainers()
    .NonLazy()
    .IfNotBound();

ContractType = The type that you are creating a binding for.

This value will correspond to the type of the field/parameter that is being injected.


ResultType = Describe to which type to bind.
Default: ContractType

This type must either to equal to ContractType or derive from ContractType.

It is not affected by any usage of ConstructionMethod


Identifier = uID to distinguish between multiple bindings with the same contract type.


ConstructionMethod = Describe how ResultType is created
Default: FromNew()

more details

eg. FromGetter, FromMethod, FromResolve, FromComponentInNewPrefab, FromSubContainerResolve, FromInstance, etc.


Scope = Describe how often the generated instance is re-used across multiple injections.

Default: AsTransient.

Note however that not all bindings have a default, so an exception will be thrown if not supplied.

Such these bindings are any construction method that is a search rather than creating a new object from scratch (eg. FromMethod, FromComponentX, FromResolve, etc.)

  • AsTransient - Will not re-use after one usage, Container will create Binding code on every usage.

  • AsCached - Will re-use the same instance of ResultType every time ContractType is requested, which it will lazily generate upon first use (Lazy by default)

  • AsSingle - Exactly the same as AsCached, except that it will sometimes throw exceptions if there already exists a binding for ResultType. It is simply a way to ensure that the given ResultType is unique within the container.

    Note however that it will only guarantee that there is only one instance across the given container, which means that using AsSingle with the same binding in a sub-container could generate a second instance.


Arguments = forwarded parameters on injecting ctor / method

Container.BindInstance(arg).WhenInjectedInto<ResultType>()

InstantiatedCallback = handiful in order to customize an object after instantiation.

In particular, using a third-party library, it might be necessary to change a few fields on one of its types.

For these cases you can pass a method to OnInstantiated that can customize the newly created instance. For example:

Container.Bind<Foo>().AsSingle().OnInstantiated<Foo>(OnFooInstantiated);

void OnFooInstantiated(InjectContext context, Foo foo) {
    foo.Qux = "asdf";
}

Note that you can also bind a custom factory using FromFactory that directly calls Container. InstantiateX before customizing it for the same effect, but OnInstantiated can be easier in some cases


Condition = The condition that must be true for this binding to be chosen. See here for more details.


NonLazy = ResultType is only ever instantiated when the binding is first used (aka "lazily"). However, when NonLazy is used, ResultType will immediately be created on startup.


IfNotBound = When this is added to a binding and there is already a binding with the given contract type + identifier, then this binding will be skipped.

profile
Unity3D Freelancer Programmer + React

0개의 댓글