());
Note that you can use the same Fluent API in the `Bind()` method as well, and you can also use it in both `Bind()` and `To()` at the same time.
-For more examples see the examples section below. The full format is as follows:
+For more examples see the [examples](#convention-binding-examples) section below. The full format is as follows:
x.InitialList().Conditional().AssemblySources()
@@ -2413,7 +2418,7 @@ x.InitialList().Conditional().AssemblySources()
1. **FromAssemblies**(assembly1, assembly2, ...) - Look up types only in the given assemblies
1. **FromAssembliesWhere**(predicate) - Look up types in all assemblies that match the given predicate
-### Examples:
+### Examples:
Note that you can chain together any combination of the below conditionals in the same binding. Also note that since we aren't specifying an assembly here, Zenject will search within all loaded assemblies.
@@ -2464,11 +2469,11 @@ Note that you can chain together any combination of the below conditionals in th
This is equivalent to calling `Container.BindInterfacesTo()` for every type in the namespace "MyGame.Things". This works because, as touched on above, Zenject will skip any bindings in which the concrete type does not actually derive from the base type. So even though we are using `AllInterfaces` which matches every single interface in every single loaded assembly, this is ok because it will not try and bind an interface to a type that doesn't implement this interface.
-## Decorator Bindings
+## Decorator Bindings
See here.
-## Open Generic Types
+## Open Generic Types
Zenject also has a feature that allow you to automatically fill in open generic arguments during injection. For example:
@@ -2536,9 +2541,9 @@ public class TestInstaller : MonoInstaller
This can sometimes open up some interesting design possibilities so good to be aware of.
-## Notes About Destruction/Dispose Order
+## Notes About Destruction/Dispose Order
-If you add bindings for classes that implement `IDisposable`, then you can control the order that they are disposed in by setting the execution order. However this is not the case for GameObjects in the scene.
+If you add bindings for classes that implement `IDisposable`, then you can control the order that they are disposed in by setting the [execution order](#update--initialization-order). However this is not the case for GameObjects in the scene.
Unity has a concept of "script execution order" however this value does not affect the order that OnDestroy is executed. The root-level game objects might be destroyed in any order and this includes the SceneContext as well.
@@ -2552,7 +2557,7 @@ If the scene destruction order is important to you, then you might consider also
The reason this setting is not set to true by default is because it can cause crashes on Android as discussed here.
-## UniRx Integration
+## UniRx Integration
UniRx is a library that brings Reactive Extensions to Unity. It can greatly simplify your code by thinking of some kinds of communication between classes as 'streams' of data. For more details see the UniRx docs.
@@ -2633,7 +2638,7 @@ public class UserDisplayWindow : IInitializable, IDisposable
In this case we have some costly operation that we want to run every time some data changes (in this case, sorting), and all it does is affect how something is rendered (in this case, a displayed list of user names). We could implement ITickable and then set a boolean flag every time the data changes, then perform the update inside Tick(), but this isn't really the reactive way of doing things, so we use Sample() instead.
-## Auto-Mocking using Moq
+## Auto-Mocking using Moq
See here.
@@ -2710,9 +2715,9 @@ Something else to note is that the rate at which the ITickable.Tick method gets
## Optimization Recommendations/Notes
-1. Use memory pools with an initial size. This should restrict all the costly instantiate operations to scene startup and allow you to avoid any performance spikes once the game starts. Or, if you want to be really thorough, you could use a fixed size, which would trigger exceptions when the pool size limit is reached.
+1. Use [memory pools](#memory-pools) with an initial size. This should restrict all the costly instantiate operations to scene startup and allow you to avoid any performance spikes once the game starts. Or, if you want to be really thorough, you could use a fixed size, which would trigger exceptions when the pool size limit is reached.
-2. Use reflection baking. This is often simply a matter of enabling it and forgetting it, and can eliminate as much as 45% of the time spent running zenject code during scene startup.
+2. Use [reflection baking](#reflection-baking). This is often simply a matter of enabling it and forgetting it, and can eliminate as much as 45% of the time spent running zenject code during scene startup.
3. Use Unity's Profiler. When Unity's profiler is open, Zenject automatically adds profiling samples for all the common zenject interface operations including IInitializable.Initialize, ITickable.Tick, IDisposable.Dispose, etc. in a similar way that unity does this automatically for all MonoBehaviour methods. So, if you implement ITickable then you should see Foo.Tick in the profiler where Foo is one of your classes.
@@ -2755,7 +2760,7 @@ You can also get minor gains in speed and minor reductions in memory allocations
For some benchmarks on Zenject versus other DI frameworks, see [here](https://github.com/svermeulen/IocPerformance) (see the charts at the bottom in particular).
-## Reflection Baking
+## Reflection Baking
One easy way to squeeze extra performance out of Zenject is to enable a feature called Reflection Baking. This will move some of the costs associated with analyzing the types in your codebase (aka reflection) from runtime to build time. In one of our products at Modest Tree, turning on baking resulted in a 45% reduction in zenject startup time (which amounted to around 424 milliseconds saved). Results vary project to project depending on how many types are used and the target platform, but is often noticeable.
@@ -2763,7 +2768,7 @@ Reflection Baking will also reduce the time taken to instantiate new objects. T
To enable for your project, simply right click somewhere in the project tab and select Create -> Zenject -> Reflection Baking Settings. Now if you build your project again, reflection costs inside Zenject should be mostly eliminated.
-By default, reflection baking will modify all the generated assemblies in your project. These include all the assemblies that Unity generates and places in the Library/ScriptAssemblies folder, and does not include any assemblies that are placed underneath the Assets directory (however you can also apply reflection baking there too as a separate step)
+By default, reflection baking will modify all the generated assemblies in your project. These include all the assemblies that Unity generates and places in the Library/ScriptAssemblies folder, and does not include any assemblies that are placed underneath the Assets directory (however you can also apply reflection baking there too as a [separate step](#reflection-baking-external-dlls))
In many cases you will want to limit which areas of the code reflection baking is applied to. You can do this by selecting the reflection baking settings object, unchecking the `All Generated Assemblies` flag, and then explicitly adding the assemblies you want to use to the `Include Assemblies` property. Or you can leave the `All Generated Assemblies` flag set to true and instead limit which assemblies are changed by adding one or more regular expressions to the Namespace Patterns field, and also changing the `Exclude Assemblies` property. For example, if all of your game code lives underneath the `ModestTree.SpaceFighter` namespace, then you could ensure that the reflection baking only applies there by adding `^ModestTree.SpaceFighter` as a namespace pattern. Note that zenject will automatically add a namespace pattern for itself so it is not necessary for you to do this (however, it is necessary to add the zenject assemblies to `Include Assemblies` if you do not have `All Generated Assemblies` checked)
@@ -2850,7 +2855,7 @@ There were also a few things that were renamed:
- Zenject.Lazy was renamed to Zenject.LazyInject to address a naming conflict with System.Lazy (We'd like to use System.Lazy directly but this causes issues on IL2CPP)
- ByNewPrefab bind method was renamed to ByNewContextPrefab
-## DiContainer Methods
+## DiContainer Methods
In addition to the bind methods documented above, there are also some other methods you might want to occasionally use on DiContainer. For example, if you are writing a custom factory, you might want to directly call one of the `DiContainer.Instantiate` methods. Or you might have a situation where another library is creating instances of your classes (for example, a networking library) and you need to manually call DiContainer.Inject.
@@ -2858,7 +2863,7 @@ DiContainer is always added to itself, so you can always get it injected into an
### DiContainer.Instantiate
-These instantiate methods might be useful for example inside a custom factory. Note however that in most cases, you can probably get away with using a normal Factory instead without needing to directly reference DiContainer.
+These instantiate methods might be useful for example inside a custom factory. Note however that in most cases, you can probably get away with using a normal [Factory](#creating-objects-dynamically) instead without needing to directly reference DiContainer.
When instantiating objects directly, you can either use DiContainer or you can use IInstantiator, which DiContainer inherits from. IInstantiator exists because often, in custom factories, you are only interested in the instantiate operation so you don't need the Bind, Resolve, etc. methods
@@ -2948,9 +2953,9 @@ When instantiating objects directly, you can either use DiContainer or you can u
```
### DiContainer.Bind
-See here
+See [here](#binding)
-### DiContainer.Resolve
+### DiContainer.Resolve
1. **DiContainer.Resolve** - Get instance to match the given type. This may involve creating a new instance or it might return an existing instance, depending on how the given type was bound.
@@ -3004,7 +3009,7 @@ See here
1. **DiContainer.ResolveTypeAll** - Same as ResolveType except returns all matches instead of assuming a single match.
-### DiContainer.Inject
+### DiContainer.Inject
1. **DiContainer.Inject** - Inject on the given instance.
@@ -3046,7 +3051,7 @@ See here
Note however that it is assumed here that there is only one match for the given component. Multiple matches (or zero matches) will generate an exception.
-### DiContainer.QueueForInject
+### DiContainer.QueueForInject
**DiContainer.QueueForInject** will queue the given instance for injection once the initial object graph is constructed.
@@ -3123,7 +3128,7 @@ Then, you can assume that A will have its inject method called before B, regardl
This is also precisely how the initial MonoBehaviour's in the scene are injected. They are all simply added to the container with the QueueForInject method.
-### DiContainer Unbind / Rebind
+### DiContainer Unbind / Rebind
It is possible to remove or replace bindings that were added in a previous bind statement. Note however that using methods are often a sign of bad practice.
@@ -3144,7 +3149,7 @@ It is possible to remove or replace bindings that were added in a previous bind
Container.Rebind().To();
```
-### Other DiContainer methods
+### Other DiContainer methods
1. **DiContainer.ParentContainers** - The parent containers for the given DiContainer. For example, for the DiContainer associated with SceneContext, this will usually be the DiContainer associated with the ProjectContext (unless you're using Scene Parenting in which case it will be another SceneContext)
1. **DiContainer.IsValidating** - Returns true if the container is being run for validation. This can be useful in some edge cases where special logic needs to be added during the validation step only.
@@ -3173,7 +3178,7 @@ It is possible to remove or replace bindings that were added in a previous bind
1. **DiContainer.GetDependencyContracts** - Returns a list of all the types that the given type depends on. This might be useful, for example, if you wanted to do some static analysis of your project, or if you wanted to automatically generate a dependency diagram, etc.
-## Frequently Asked Questions
+## Frequently Asked Questions
* **Isn't this overkill? I mean, is using statically accessible singletons really that bad?**
@@ -3237,7 +3242,7 @@ It is possible to remove or replace bindings that were added in a previous bind
* **How is performance?**
- See here
+ See [here](#optimization_notes)
* **Does Zenject support multithreading?**
@@ -3345,21 +3350,21 @@ It is possible to remove or replace bindings that were added in a previous bind
* **I keep getting errors complaining about circular reference! How to address this?**
-If two classes are injected into each other and both classes use contructor injection, then obviously it is not possible for zenject to create both of these classes. However, what you can do instead is switch to use method injection or field/property injection instead. Or, alternatively, you could use the LazyInject<> construct
+If two classes are injected into each other and both classes use contructor injection, then obviously it is not possible for zenject to create both of these classes. However, what you can do instead is switch to use method injection or field/property injection instead. Or, alternatively, you could use the [LazyInject<>](#just-in-time-resolve) construct.
## Cheat Sheet
See here.
-## Further Help
+## Further Help
For general troubleshooting / support, please use the [zenject subreddit](http://www.reddit.com/r/zenject) or the [zenject google group](https://groups.google.com/forum/#!forum/zenject/). If you have found a bug, you are also welcome to create an issue on the [github page](https://github.com/svermeulen/Extenject), or a pull request if you have a fix / extension. Finally, you can also email me directly at sfvermeulen@gmail.com or follow me on twitter at [@steve_verm](https://twitter.com/steve_verm)
-## Release Notes
+## Release Notes
See here.
-## License
+## License
The MIT License (MIT)