Search Unity

[RELEASED] Zenject Dependency Injection Framework

Discussion in 'Assets and Asset Store' started by eventropy, Jun 3, 2014.

  1. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    106
    Hello @eventropy !

    We are having a problem. When we use InstantiateComponentOnNewGameObject, [PostInject] method is called twice. Please see the two call stack, maybe you figure out what could be the problem.
    Could you suggest us a workarround to not use InstantiateComponentOnNewGameObject?

    Thank you.

    First call (We think the buggy one. See line 38)
    Code (CSharp):
    1.  
    2. Void SimuZen.Services.OrchestratorFromList:Initialize ()+0x0 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\platform\systems\base\services\orchestrator\OrchestratorFromList.cs:53    C#
    3.      Object System.Reflection.MonoMethod:Invoke (Object, BindingFlags, Binder, Object[], CultureInfo)+0xd6 at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222    C#
    4.      Object System.Reflection.MethodBase:Invoke (Object, Object[])+0x6 at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115    C#
    5.      Void Zenject.DiContainer:InjectExplicit (Object, IEnumerable`1, Boolean, ZenjectTypeInfo, InjectContext, String)+0x183 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:779    C#
    6.      Void Zenject.DiContainer:Inject (Object, IEnumerable`1, Boolean, InjectContext, ZenjectTypeInfo)+0x28 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1265    C#
    7.      Void Zenject.DiContainer:Inject (Object, IEnumerable`1, Boolean, InjectContext)+0x11 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1254    C#
    8.      Void Zenject.DiContainer:InjectGameObject (GameObject, Boolean, Boolean, IEnumerable`1, InjectContext)+0x62 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1229    C#
    9.      Object Zenject.PrefabSingletonLazyCreator:GetComponent (Type, InjectContext)+0xf9 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\SingletonCreators\PrefabSingletonLazyCreator.cs:108    C#
    10.      Object Zenject.PrefabSingletonProvider:GetInstance (InjectContext)+0xd at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\PrefabSingletonProvider.cs:39    C#
    11.      Object Zenject.DiContainer:SafeGetInstance (ProviderBase, InjectContext)+0x77 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:600    C#
    12.      Object Zenject.DiContainer:Resolve (InjectContext)+0x167 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:581    C#
    13.      Void Zenject.DiContainer:InjectExplicit (Object, IEnumerable`1, Boolean, ZenjectTypeInfo, InjectContext, String)+0xa1 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:744    C#
    14.      Void Zenject.DiContainer:Inject (Object, IEnumerable`1, Boolean, InjectContext, ZenjectTypeInfo)+0x28 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1265    C#
    15.      Void Zenject.DiContainer:Inject (Object, IEnumerable`1, Boolean, InjectContext)+0x11 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1254    C#
    16.      Void Zenject.DiContainer:InjectGameObject (GameObject, Boolean, Boolean, IEnumerable`1, InjectContext)+0x62 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1229    C#
    17.      Object Zenject.PrefabSingletonLazyCreator:GetComponent (Type, InjectContext)+0xf9 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\SingletonCreators\PrefabSingletonLazyCreator.cs:108    C#
    18.      Object Zenject.PrefabSingletonProvider:GetInstance (InjectContext)+0xd at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\PrefabSingletonProvider.cs:39    C#
    19.      Object Zenject.DiContainer:SafeGetInstance (ProviderBase, InjectContext)+0x77 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:600    C#
    20.      Object Zenject.DiContainer:Resolve (InjectContext)+0x167 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:581    C#
    21.      Void Zenject.DiContainer:InjectExplicit (Object, IEnumerable`1, Boolean, ZenjectTypeInfo, InjectContext, String)+0xa1 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:744    C#
    22.      Void Zenject.SingletonLazyCreatorByType:InitInstance (InjectContext)+0x6c at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\SingletonCreators\SingletonLazyCreatorByType.cs:45    C#
    23.      Object Zenject.SingletonLazyCreatorByType:GetInstance (InjectContext)+0xd at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\SingletonCreators\SingletonLazyCreatorByType.cs:25    C#
    24.      Object Zenject.SingletonProvider:GetInstance (InjectContext)+0x7 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\SingletonProvider.cs:32    C#
    25.      Object Zenject.DiContainer:SafeGetInstance (ProviderBase, InjectContext)+0x77 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:600    C#
    26.      Object Zenject.DiContainer:Resolve (InjectContext)+0x167 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:581    C#
    27.      Void Zenject.DiContainer:InjectExplicit (Object, IEnumerable`1, Boolean, ZenjectTypeInfo, InjectContext, String)+0xa1 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:744    C#
    28.      Void Zenject.SingletonLazyCreatorByType:InitInstance (InjectContext)+0x6c at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\SingletonCreators\SingletonLazyCreatorByType.cs:45    C#
    29.      Object Zenject.SingletonLazyCreatorByType:GetInstance (InjectContext)+0xd at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\SingletonCreators\SingletonLazyCreatorByType.cs:25    C#
    30.      Object Zenject.SingletonProvider:GetInstance (InjectContext)+0x7 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Providers\SingletonProvider.cs:32    C#
    31.      Object Zenject.DiContainer:SafeGetInstance (ProviderBase, InjectContext)+0x77 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:600    C#
    32.      Object Zenject.DiContainer:Resolve (InjectContext)+0x167 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:581    C#
    33.      Void Zenject.DiContainer:InjectExplicit (Object, IEnumerable`1, Boolean, ZenjectTypeInfo, InjectContext, String)+0xa1 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:744    C#
    34.      Void Zenject.DiContainer:InjectExplicit (Object, List`1, InjectContext)+0x11 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1277    C#
    35.      Object Zenject.DiContainer:InstantiateComponentOnNewGameObjectExplicit (Type, String, List`1, InjectContext)+0x56 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:867    C#
    36.      Object Zenject.DiContainer:InstantiateComponentOnNewGameObjectExplicit (Type, String, List`1)+0xc at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1168    C#
    37.      Object Zenject.DiContainer:InstantiateComponentOnNewGameObject (Type, String, Object[])+0x27 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1154    C#
    38.      Object Zenject.DiContainer:InstantiateComponentOnNewGameObject (String, Object[])+0xd at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1145    C#
    39.      Void EnvironmentInstaller:InstallEnvironmentService ()+0x50 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\platform\installers\EnvironmentInstaller.cs:38    C#
    40.      Void EnvironmentInstaller:InstallBindings ()+0x1 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\platform\installers\EnvironmentInstaller.cs:20    C#
    41.      Void Zenject.DiContainer:InstallInstallerInternal (IInstaller)+0x85 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:469    C#
    42.      Void Zenject.DiContainer:Install (IInstaller)+0x14 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:401    C#
    43.      Void Zenject.DiContainer:Install (IEnumerable`1)+0x2b at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:391    C#
    44.      DiContainer Zenject.SceneCompositionRoot:CreateContainer (Boolean, DiContainer, List`1)+0xc7 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\SceneCompositionRoot.cs:119    C#
    45.      Void Zenject.SceneCompositionRoot:InitContainer ()+0x12 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\SceneCompositionRoot.cs:151    C#
    46.      Void Zenject.SceneCompositionRoot:Awake ()+0x3d at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\SceneCompositionRoot.cs:59    C#
    47.  
    Second call (And we think the good one):
    Code (CSharp):
    1. >  
    2. Void SimuZen.Services.OrchestratorFromList:Initialize ()+0x0 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\platform\systems\base\services\orchestrator\OrchestratorFromList.cs:53    C#
    3.      Object System.Reflection.MonoMethod:Invoke (Object, BindingFlags, Binder, Object[], CultureInfo)+0xd6 at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222    C#
    4.      Object System.Reflection.MethodBase:Invoke (Object, Object[])+0x6 at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115    C#
    5.      Void Zenject.DiContainer:InjectExplicit (Object, IEnumerable`1, Boolean, ZenjectTypeInfo, InjectContext, String)+0x183 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:779    C#
    6.      Void Zenject.DiContainer:Inject (Object, IEnumerable`1, Boolean, InjectContext, ZenjectTypeInfo)+0x28 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1265    C#
    7.      Void Zenject.DiContainer:Inject (Object, IEnumerable`1, Boolean, InjectContext)+0x11 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1254    C#
    8.      Void Zenject.DiContainer:InjectGameObject (GameObject, Boolean, Boolean, IEnumerable`1, InjectContext)+0x62 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1229    C#
    9.      Void Zenject.DiContainer:InjectGameObject (GameObject, Boolean, Boolean, IEnumerable`1)+0x7 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1199    C#
    10.      Void Zenject.DiContainer:InjectGameObject (GameObject, Boolean, Boolean)+0x9 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\DiContainer.cs:1180    C#
    11.      Void Zenject.SceneCompositionRoot:InjectObjectsInScene ()+0x59 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\SceneCompositionRoot.cs:175    C#
    12.      Void Zenject.SceneCompositionRoot:Awake ()+0x53 at D:\Users\MANUEL ESPINO\Workspace HDD\Simescar 2.0\Simuplatform\simuzen\Assets\externals\zenject\Source\Main\SceneCompositionRoot.cs:62    C#
    13.  
    Edit: I have changed InstantiateOnNewGameObject by InstantiatePrefab with a prefab and I have the same problem and the same callstack
     
    Last edited: Feb 25, 2016
  2. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Hey, sorry, I missed this post somehow.

    Yes, the installers can be used to define the pure C# classes that you are using to implement your game. By binding them to the Zenject interfaces IInitializable, ITickable, IDisposable, etc. you can have these pure C# objects perform similar operations that you would normally use a MonoBehaviour for.

    Also, the installer isn't just used to map interfaces to concrete types, that's a common misconception with DI (see here: https://github.com/modesttree/zenject#misconceptions).

    Also, I'm not sure I understand what you mean about MonoInstallers exist to define values on an instance. If you mean, to supply settings data, you can do that in installers too (see here: https://github.com/modesttree/zenject#using-the-unity-inspector-to-configure-settings)

    Zenject is completely general purpose - I would recommend it for any kind of app. So your use case seems good for it.
     
  3. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    I don't have any specific recommendations here, sorry. As you say, it's outside the scope of DI with Zenject. Maybe other people have thoughts?
     
  4. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    What version of Zenject are you using?
     
  5. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    @Maeslezo

    Oh ok I think I see the issue. It looks like you are creating a new object in "EnvironmentInstaller:InstallEnvironmentService". This is bad practice in DI - you shouldn't mix calls to instantiate or resolve in with your bindings. Ideally, you would set up a container to be "fully bound" and then and only then instantaite anything.

    So installers should just hook up bindings and that's it (this is also important if you use validation to check your object graphs at edit-time).

    After all the installers have been run, Zenject goes through all the game objects in your scene and injects on them. And so that's how it gets injected twice. Zenject assumes that you don't instantiate new game objects in your installers.

    If you can, it would be better to move the code that is instantiating a new game object to a Start event (or use an IInitializable)

    Having said that, it might be possible to address this on Zenject's side by caching the list of starting objects before calling installers and then only injecting on those instead of everything that's in the scene. But then we might get issues if people delete objects in their installers so that might be messy.

    Another workaround for your case would be to just call AddComponent in your installer and then let Zenject inject on it the second time (though again, best practice would be to wait until Start to create objects dynamically)
     
    Maeslezo likes this.
  6. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    106
    Thank you for your reply! We will try your suggestions. I have two more question about this.

    - You say "you shouldn't mix calls to instantiate or resolve in with your bindings". So, Container.Bind<Foo>().ToSinglePrefab(fooPrefab) would be a bad practise?

    - Following the zenject examples, imaging I have a Ship, but this ship could be of 3 different kinds. The ship must be injected in other classes that need it. If I create the ship after the inject process, the other classes won't have the ship injected. So, if I have 3 ships, and I will know the type in runtime by a parameter, when do I instantiate the ship and do the binding?

    Thank you very much. I really appreciate your help.
     
  7. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Hey, sorry for the late response.

    No, `Container.Bind<Foo>().ToSinglePrefab(fooPrefab)` is fine, since that is a binding. I'm saying that in general, it's best to avoid calling `Container.Instantiate` or `Container.Resolve` from within installers. Better to only call `Container.Bind`. The only reason I say this is because calls to `Container.Instantiate` will use the bindings when constructing the object, and so you want to ensure all bindings have been added before that is called.

    I would still use a binding for this. For example, here is one way to do it:

    Code (CSharp):
    1.    
    2.     public class Ship
    3.     {
    4.     }
    5.  
    6.     public class Ship1 : Ship
    7.     {
    8.     }
    9.  
    10.     public class Ship2 : Ship
    11.     {
    12.     }
    13.  
    14.     public override void InstallBindings()
    15.     {
    16.         Container.Bind<Ship>().ToSingleMethod<Ship>(CreateShip);
    17.     }
    18.  
    19.     Ship CreateShip(InjectContext context)
    20.     {
    21.         if (new Random().NextDouble() < 0.5f)
    22.         {
    23.             return new Ship1();
    24.         }
    25.  
    26.         return new Ship2();
    27.     }
    28.  
    Or, if you want your ships to be injected too, you'd change it to:

    Code (CSharp):
    1.    
    2.     Ship CreateShip(InjectContext context)
    3.     {
    4.         if (new Random().NextDouble() < 0.5f)
    5.         {
    6.             return Container.Instantiate<Ship1>();
    7.         }
    8.  
    9.         return Container.Instantiate<Ship2>();
    10.     }
    11.  
    Here I use ToSingleMethod but you could also use ToMethod. The only difference is that with ToSingleMethod the method would only be called once and then the result would be re-used everywhere.

    If there is a lot of logic to the CreateShip method, you might also want to use ToSingleFactory instead. This is also nice in cases where the construction of the ship requires dependencies out of the container as well. With a factory, you can just add constructor parameters (whereas with the CreateShip method you'd have to call Container.Resolve which can get ugly).
     
    Maeslezo likes this.
  8. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    815
    What's the easiest way of using pools? I am using Pool Manager from the asset store and I have no idea how to use it with zenject. Any ideas or does anybody use it?
     
  9. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    106
    Ok, I get it. The problem I see on this is when you know the ship you have to instantiate in IInitalize time (or in other moment) but not in Installer time. And if you don't bind a ship in installer time, all the ship dependencies will fail. Could be a solution to bind a dummyShip and then do a rebind?
     
  10. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    No, binding a dummy ship shouldn't be necessary. Like I said in my last post, you can bind your ship at Install time without needing to actually create it, by using things like ToMethod, ToSingleMethod, ToSingleFactory, etc. Doesn't that solve your problem or am I misunderstanding?
     
    Maeslezo likes this.
  11. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    There isn't any specific support for pools in Zenject (yet). But what you can do is use another third party pooling solution, and then use Zenject to call Inject() on it after you receive the new instance, to fill in its dependencies.
     
  12. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    106
    Sorry, probably I am not explaining myself (I think it is a little tricky). When you bind, it is true that you do not need to create an instance, but when you inject, (in inject time), it is necessary.

    Imaging that the ship type comes from a server, so I need to wait asynchronously the server response. When the server reply, I know the ship type and I can create it, but never before. But I can not do this because the [Inject]ship have failed.

    According the documentation (https://github.com/modesttree/Zenject#zenject-order-of-operations) , step 6 injects all the dependencies, but what about if I am not ready in step 6 to create the object?

    If I didn't explain myself already I could do a little sample project with the problem.

    Reading further the documentation, I found
    Maybe abstract factory is the solution. What do you think?
     
  13. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Ok I'm starting to understand what you're saying.

    Sounds like you're saying you have a class like this:

    Code (CSharp):
    1.  
    2.     public class Foo
    3.     {
    4.         [Inject]
    5.         Ship _ship;
    6.     }
    7.  
    And in your installer you bind it like this:

    Code (CSharp):
    1.  
    2.     public override void InstallBindings()
    3.     {
    4.         Container.Bind<Foo>().ToSingle();
    5.     }
    6.  
    But you cannot add a binding for the Ship class to the installer because you don't know which ship to use yet. Let's assume like you said that the Ship type is provided asynchronously from a server at some point after startup.

    It seems to me that in this case your options are:

    1. Use a public setter method to supply the ship to Foo after Foo has already been created
    2. Remove the "Container.Bind<Foo>()" line from your installer and instead create Foo dynamically using a factory, after you get the ship type from the server, then pass it the ship as a parameter
    3. Use another scene to do the async loading, then load the main scene and pass the ship type into it as a parameter to the installer, then you can bind the Ship in the installer
     
    Maeslezo likes this.
  14. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    106
    I think I am using option 2. Option 1 is fine for a small example, but I do not think is maintainable and scalable. Option 3 is too much workaround.
    I will inject a factory with an event. When the server is ready, the ship is created in the factory and OnShipCreated event is sent. The other objects can get the event and take the ship created.

    Thank you very much
     
  15. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    106
    Hello again,

    Is there any way to inject into Playmaker actions?

    Thank you.
     
  16. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Oops, sorry didn't see this post.

    I'm not familiar with Playmaker, but you can always inject manually by calling Container.Inject(myObject) (assuming you can execute code after Playmaker creates the class)
     
    Maeslezo likes this.
  17. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    106
    Thank you.

    For others that could be interested, this should do the trick:

    Code (CSharp):
    1. using HutongGames.PlayMaker;
    2. using UnityEngine;
    3. using Zenject;
    4.  
    5. [RequireComponent(typeof(PlayMakerFSM))]
    6. public class FsmInjector : MonoBehaviour
    7. {
    8.     [PostInject]
    9.     private void Inject(DiContainer container)
    10.     {
    11.         PlayMakerFSM playMakerFsm = this.GetComponent<PlayMakerFSM>();
    12.         Fsm fsm = playMakerFsm.Fsm;
    13.  
    14.         foreach (FsmState fsmState in fsm.States)
    15.         {
    16.             foreach (FsmStateAction action in fsmState.Actions)
    17.             {
    18.                 container.Inject(action);
    19.             }
    20.         }
    21.     }
    22.  
    23. }
     
    eventropy likes this.
  18. TokyoDan

    TokyoDan

    Joined:
    Jun 16, 2012
    Posts:
    1,080
    Wow! Just installed Zenject, and loaded the Asteroids 'SampleGame1 (Beginner)' to learn how to better architect my code so that it'll save time down the road. But there are 90 million C# files in there. It'll take me the rest of my life to learn it all.
     
  19. zyzyx

    zyzyx

    Joined:
    Jul 9, 2012
    Posts:
    222
  20. TokyoDan

    TokyoDan

    Joined:
    Jun 16, 2012
    Posts:
    1,080
    I always read the documentation. But still, all those C# files. Is it necessary to look over and understand all of them?
     
  21. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    It's definitely not necessary to understand the entire sample game - most of that is just code specific to the game rather than Zenject. I tried to make an actual game rather than just a Hello World kind of sample, but I also tried to keep it as simple as possible. It's tough to keep it bare bones simple while also making something somewhat interesting though
     
    zyzyx likes this.
  22. TokyoDan

    TokyoDan

    Joined:
    Jun 16, 2012
    Posts:
    1,080
    Thanks. I'll take a look. All those source files almost scared me away but I'll hang in there.

    Just wondering...what is your opinion on using zenject compared to one of the ECS assets. (Isn't IoC/DI more suitable and enough without the extra ECS baggage on top of Unity which is already basically ECS?)

    1. Since Unity is already basically ECS, isn't using an ECS asset on top of Unity over-engineering and just convoluting things?
    2. What do you think about Svelto-ECS recommending not to use IoC Containers?
     
    Last edited: Jun 1, 2016
  23. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    I haven't tried any of the ECS frameworks actually. I've read some of the articles on it, but I don't feel like I am informed/experienced enough to really comment much. So take what I'm about to say with a grain of salt :)

    One of the things I really like about DI frameworks is that they aren't very opinionated in how you design your code (unlike a lot of these frameworks like Svelto-ECS). Zenject tries to get out of the way as much as possible and let you create whatever kind of architecture you want. If you do things right, you won't even be all that "coupled" to Zenject. In theory, you could abandon Zenject and go back to poor-man's DI, or use another DI framework.

    Some would argue that being un-opinionated is a bad thing (which I think Seba does in that article) since it allows programmers which are not experienced in code design to create bad designs. Which might be true, but I wouldn't consider that a fault of the framework.

    Speaking for myself, I would be far more reluctant to put so much faith in one of these rigid frameworks, especially when the claim is that it is completely general purpose and can apply to any software problem. I feel like rigid frameworks really work best when you can apply domain-specific constraints (which you can actually do to some extent with Zenject by using convention based binding)

    To me, DI and DI frameworks are pretty fundamental and really just the logical next step when writing object oriented code. It allows every class to just declare the contracts that it needs fulfilled (as concrete classes or interfaces, it doesn't matter since it can still be thought of as just contracts in an abstract sense). Then just fulfills whatever single responsibility it has by using those contracts.
     
  24. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,179
    @eventropy I seem to running into an issue where dynamically instantiated GameObjects with multiple components attached are not being properly injected at runtime.
    Code (csharp):
    1. public class A : MonoBehaviour
    2. {
    3.      private Manager manager = null;
    4.  
    5.      [Inject]
    6.      public void Construct(Manager newManager)
    7.      {
    8.           manager = newManager;
    9.      }
    10. }
    11.  
    12. public class B : MonoBehaviour
    13. {
    14.      private Manager manager = null;
    15.  
    16.      [Inject]
    17.      public void Construct(Manager newManager)
    18.      {
    19.           manager = newManager;
    20.      }
    21. }
    22.    
    23. public class Manager
    24. {
    25. }
    26.  
    27. public void Main()
    28. {
    29.      GameObject goWithAAndBComponents = Instantiate(otherGameObject);
    30. }
    I'm trying to Inject a Manager object into a GameObject when it is instantiated, but I need to Inject into multiple Components (A & B) attached to the same GameObject when it is Instantiated. I tried to use your Factory MonoBehaviour example, but that did not seem to work. Do you have any suggestions on how to do this?
     
  25. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    You can't use "Instantiate" on objects with [Inject] methods or properties (it's in the documentation). The easiest way to fix it in my opinion is to add an IInstantiator to whatever class that "Main" method is in. IInstantiator is a Zenject interface that will automatically handle filling out the dependencies in new game objects:
    Code (csharp):
    1. public class MainThing
    2. {
    3.     private IInstantiator instantiator;
    4.    
    5.     [Inject]
    6.     public void Construct(IInstantiator newInstantiator)
    7.     {
    8.            instantiator = newInstantiator;
    9.     }
    10.  
    11.     public void Main()
    12.     {
    13.            GameObject goWithAAndBComponents = instantiator.Instantiate(otherGameObject);
    14.      }
    15. }
     
  26. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,179
    I'll try that. Would I bind IInstantiator like this if I wanted the same IInstantiator used across classes, or do I need to BinInterfaces as well?
    Code (csharp):
    1. Container.Bind<IInstantiator>().AsSingle();
    EDIT:
    It looks like that did the trick! Thanks @makeshiftwings . I just wrote the Binding as this:
    Code (csharp):
    1. Container.BindAllInterfaces<IInstantiator>().To<IInstantiator>().AsSingle();
     
    Last edited: Jun 30, 2016
  27. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    I don't think you actually have to bind IInstantiator at all; I think it just automatically gets bound. But I guess it doesn't hurt to include it.
     
  28. sanchoflat

    sanchoflat

    Joined:
    Jun 9, 2013
    Posts:
    14
    Hello, @eventropy. I'm interesting, how can I create this:
    Code (CSharp):
    1. // this is singleton
    2. public class AppManager {
    3.     public int LevelNum { get { return 3; } }
    4. }
    5.  
    6. public class TestInstaller : MonoInstaller {
    7.     public override void InstallBindings() {
    8.         Container.Bind<AppManager>().AsSingle();
    9.         Container.Bind<LevelBehavior>().FromFactory<LevelBehavior.LevelFactory>();
    10.     }
    11. }
    12.  
    13. public class LevelBehavior {
    14.     public class LevelFactory : IFactory<LevelBehavior> {
    15.      
    16.         // -----------------------------------------------
    17.         // For example I have not only this factory. A lot of factories
    18.         // Should I inject _appManager in all my factories to create leveldependent content?
    19.         [Inject]
    20.         private AppManager _appManager;
    21.         // -----------------------------------------------
    22.  
    23.         public LevelBehavior Create() {
    24.             return Create(_appManager.LevelNum);
    25.         }
    26.  
    27.         private LevelBehavior Create(int level) {
    28.             switch(level) {
    29.                 case 1:
    30.                     return new Level1Behavior();
    31.                 case 2:
    32.                     return new Level2Behavior();
    33.                 case 3:
    34.                     return new Level3Behavior();
    35.                 case 4:
    36.                     return new Level4Behavior();
    37.             }
    38.             return null;
    39.         }
    40.     }
    41. }
    42.  
    43. public class Level1Behavior : LevelBehavior {}
    44.  
    45. public class Level2Behavior : LevelBehavior {}
    46.  
    47. public class Level3Behavior : LevelBehavior {}
    48.  
    49. public class Level4Behavior : LevelBehavior {}
    Thank you.
     
  29. DreamEnder

    DreamEnder

    Joined:
    Apr 12, 2011
    Posts:
    190
    Hi. I recently purchased Quick Golf (http://u3d.as/xym) off the Asset Store and I see it uses Zenject. Everything works great on iOS however when I launch on Android nothing loads in the game. It shows the Title screen however nothing gets initialised. There are no error messages either. Any ideas what's up?
     
  30. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    This sounds like an issue with Quick Golf and not an issue with Zenject. So I think you'd be best off asking the author of Quick Golf
     
  31. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    815
    Hi! Any idea what this error means: http://prntscr.com/d0rty0
    I have pretty simple installer setup here is the code:
    Code (CSharp):
    1. using Zenject;
    2.  
    3. namespace Game.Race3D
    4. {
    5.     public class GameInstaller : MonoInstaller
    6.     {
    7.         public override void InstallBindings()
    8.         {
    9.             InstallGameController();
    10.         }
    11.  
    12.         void InstallGameController()
    13.         {
    14.             Container.Bind<ITickable>().To<GameController>().AsSingle();
    15.             Container.Bind<IInitializable>().To<GameController>().AsSingle();
    16.             Container.Bind<GameController>().AsSingle();
    17.             Container.Bind<IGame>().To<GameController>().AsSingle();
    18.         }
    19.     }
    20. }
    21.  
    Let me just add, that it happens with example scenes as well, I am on 5.3.5
     
  32. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    What version of zenject are you using? There should be a version.txt file in the root zenject folder
     
  33. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    815
    Hi error seemed to go away when I used new version of Unity, I am using latest Zenject.
    I am a beginner with DI and i have an idea how this should be used...I am wondering about separation of installers, is there a example how can I reuse installers in different projects? what kind of things i would have in separate installer and what is the best way to do it?
    thanks!
     
  34. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Glad you fixed your error. For re-using installers across scenes/projects, you're options are either to use Prefabs, Scriptable Objects, or plain C# Installers. You can read about these approaches here
     
  35. Aston-Martin

    Aston-Martin

    Joined:
    Jul 5, 2012
    Posts:
    47
    Hi,

    Need help! SOS...

    Using Zenject 4.3, when i tried to build window universal10, IL2CPP with unity5.3.5. Getting error in TypeExtension.cs

    Assets\Zenject\Source\Internal\TypeExtensions.cs(29,65): error CS1061: 'Type' does not contain a definition for 'GetTypeInfo' and no extension method 'GetTypeInfo' accepting a first argument of type 'Type' could be found (are you missing a using directive or an assembly reference?)

    Similar error with zenject3.1....Need some hints to fix this... thank you!

    Br,
    AM
     
    Last edited: Nov 3, 2016
  36. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Any chance you could upgrade to the latest version? This issue should be fixed there
     
    Aston-Martin likes this.
  37. Aston-Martin

    Aston-Martin

    Joined:
    Jul 5, 2012
    Posts:
    47
    Ok thank!

    Proceed to delete v4.3 from the project and imported v4.6, run on editor 5.3.5 no errors.
    When build using scripting backend IL2CPP, Universal10, XAML.
    Unity console display:

    Assets\Zenject\Source\Internal\TypeExtensions.cs(29,65): error CS1061: 'Type' does not contain a definition for 'GetTypeInfo' and no extension method 'GetTypeInfo' accepting a first argument of type 'Type' could be found (are you missing a using directive or an assembly reference?)
    ....


    S.O.S, Anything i missed ?
     
    Last edited: Nov 4, 2016
  38. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Sorry - maybe this isn't fixed as I thought. I'm taking a look now.
     
  39. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Ok this should be fixed now. This will be included in version 4.7 but if need it now you can also just download the Zenject folder directly from the repo here: https://github.com/modesttree/zenject
     
  40. Aston-Martin

    Aston-Martin

    Joined:
    Jul 5, 2012
    Posts:
    47
    Thank you! can't wait to try it out....

    Replace zenject folder with v4.7 from GitHub.
    In unity5.3.5 console :

    Code (CSharp):
    1. Unhandled Exception: System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
    2.  
    3.   at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
    4.  
    5.   at System.Reflection.Assembly.GetTypes () [0x00000] in <filename unknown>:0
    6.  
    7.   at Mono.CSharp.RootNamespace.ComputeNamespaces (System.Reflection.Assembly assembly, System.Type extensionType) [0x00000] in <filename unknown>:0
    8.  
    9.   at Mono.CSharp.RootNamespace.ComputeNamespace (Mono.CSharp.CompilerContext ctx, System.Type extensionType) [0x00000] in <filename unknown>:0
    10.  
    11.   at Mono.CSharp.GlobalRootNamespace.ComputeNamespaces (Mono.CSharp.CompilerContext ctx) [0x00000] in <filename unknown>:0
    12.  
    13.   at Mono.CSharp.Driver.LoadReferences () [0x00000] in <filename unknown>:0
    14.  
    15.   at Mono.CSharp.Driver.Compile () [0x00000] in <filename unknown>:0
    16.  
    17.   at Mono.CSharp.Driver.Main (System.String[] args) [0x00000] in <filename unknown>:0
    18.  
    19. The class System.ComponentModel.ICancelAddNew could not be loaded, used in System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    20. The class System.ComponentModel.INotifyPropertyChanging could not be loaded, used in System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    21. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    22. The class Castle.Components.DictionaryAdapter.IDictionaryNotify could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    23. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    24. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    25. The class System.ComponentModel.PropertyChangingEventArgs could not be loaded, used in System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    26. The class Castle.Components.DictionaryAdapter.IBindingList`1 could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    27. The class Castle.Components.DictionaryAdapter.IBindingList`1 could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    28. The class Castle.Components.DictionaryAdapter.ListProjection`1 could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    29. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    30. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    31. The class Castle.Components.DictionaryAdapter.Xml.XmlAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    32. The class Castle.Components.DictionaryAdapter.Xml.XmlNodeAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    33. The class Castle.Components.DictionaryAdapter.Xml.XmlNodeAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    34. The class Castle.Components.DictionaryAdapter.Xml.XmlNodeAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    35. The class Castle.Components.DictionaryAdapter.Xml.XmlNodeAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    36. The class Castle.Components.DictionaryAdapter.Xml.XmlAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    37. The class Castle.Components.DictionaryAdapter.Xml.XmlAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    38. The class Castle.Components.DictionaryAdapter.ListProjection`1 could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    39. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    40. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    41. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    42. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    43. The class System.ComponentModel.BindingList`1 could not be loaded, used in System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    44. The class System.Diagnostics.EventLog could not be loaded, used in System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    45. The class Castle.Components.DictionaryAdapter.AbstractDictionaryAdapterVisitor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    46. The class Edit could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    47. The class SuppressEditingScope could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    48. The class NotificationSuppressionScope could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    49. The class TrackPropertyChangeScope could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    50. The class <>c__DisplayClass4 could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    51. The class <>c__DisplayClass7 could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    52. The class <>c__DisplayClass1a could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    53. The class <GetEnumerator>d__0 could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    54. The class Castle.Components.DictionaryAdapter.Xml.XmlNodeAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    55. The class Castle.Components.DictionaryAdapter.Xml.XmlNodeAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    56. The class DummyContext could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    57. The class Castle.Components.DictionaryAdapter.Xml.XPathBehaviorAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    58. The class Castle.Components.DictionaryAdapter.Xml.XPathBehaviorAccessor could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    59. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    60. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    61. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    62. The class Castle.Components.DictionaryAdapter.IDictionaryAdapter could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    63. The class <>c__DisplayClassa could not be loaded, used in Moq, Version=4.2.1308.2321, Culture=neutral, PublicKeyToken=69f491c39445e920
    64. The class System.ComponentModel.BindingList`1 could not be loaded, used in System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    65. The class System.ComponentModel.BindingList`1 could not be loaded, used in System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    Anything, i did incorrectly ?
     
    Last edited: Nov 4, 2016
  41. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    That looks unrelated to zenject. Looks like something about castle windsor?
     
  42. Aston-Martin

    Aston-Martin

    Joined:
    Jul 5, 2012
    Posts:
    47
    Hmmm not sure as well...
    Create an empty project, and unity is "dishing-out" the same exceptions....puzzled...
    Dropbox link : https://www.dropbox.com/s/laiy5jj7vmlqin5/TestZenject.rar?dl=0

    Anyway, proceed to build :
    Get theses "NEW" error from my codes (Oops) :
    Code (CSharp):
    1. Assets\Game\Scripts\DI_Related\Main\GameSignal.cs(74,37): error CS0305: Using the generic type 'Signal<TDerived>' requires 1 type arguments
    2. Assets\Game\Scripts\DI_Related\Main\GameSignal.cs(76,32): error CS0246: The type or namespace name 'TriggerBase' could not be found (are you missing a using directive or an assembly reference?)
    3.  
    From this code :
    Code (CSharp):
    1.     public class ReturnStepSignal : Signal
    2.     {
    3.         public class Trigger : TriggerBase { }
    4.     }
    5.  
    S.O.S : How do i fix the code for v4.7 ? thanks again!....
     
    Last edited: Nov 4, 2016
  43. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    The error you posted specifically complains about Castle Windsor classes. Are you saying you create an empty project with Zenject and then it still complains about Castle Windsor?

    Yeah, Zenject 4.7 introduces a breaking change to Signals. There is no trigger class anymore.

    If you don't want to update your code, you could also just copy the file TypeExtensions.cs from Zenject 4.7 into 4.6.

    This is how they work now:

    Just like before, you define an empty class like this:

    Code (CSharp):
    1.  
    2. public class PressedButtonSignal : Signal<PressedButtonSignal>
    3. {
    4. }
    5.  
    Then in an installer:

    Code (CSharp):
    1.  
    2. Container.BindSignal<PressedButtonSignal>();
    3.  
    Then in the firing class:

    Code (CSharp):
    1.  
    2. _signal.Fire();
    3.  
    And listening classes:

    Code (CSharp):
    1.  
    2. _signal += OnButtonPressed;
    3.  
    4. void OnButtonPressed()
    5. {
    6. }
    7.  
    8. _signal -= OnButtonPressed;
    9.  
     
  44. Aston-Martin

    Aston-Martin

    Joined:
    Jul 5, 2012
    Posts:
    47
    This method works for v4.6. ThumbUP! Thanks!
    Will test out with v3.10....Hope to kill 2 birds with 1 stone...

    Yes, no clue why....
     
    Last edited: Nov 4, 2016
  45. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    815
    Hi, how to get new 4.7? i want to try new version of signals
     
  46. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    I was waiting to update the documentation but I've done that now. You can download it from the releases page or wait a week or so for asset store to update.
     
  47. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    815
    thanks, i have update to 4.7 and tried to use signals, i did exactly what was in documentation
    i have made signal class,bound it in installer, inject it into game controller which has IInitializable and IDisposable methods implemented (it is as well bound in installer). signal.Listen(OnSignal) in Initialize method and signal.Unlisted(OnSignal) in Dispose method, no signal.Fire()

    when play and stop editor I get this error:
    ZenjectException: Assert hit! Found 1 methods still added to signal 'OnGameInitializedSignal'. Methods: GameController.OnSignal
    Rethrow as ZenjectException: Error occurred while disposing IDisposable with type 'OnGameInitializedSignal'

    what is wrong?
     
  48. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    This error message means that you called Listen but did not call Unlisten. Can you set a breakpoint to ensure that you call Unlisten?

    If you don't care about this error, you can disable it by commenting out the asserts in Signal1.cs, Signal2.cs, etc.
     
  49. pretender

    pretender

    Joined:
    Mar 6, 2010
    Posts:
    815
    Hi! Thanks for responding, here is the code:
    Code (CSharp):
    1. namespace Game.Race3D
    2. {
    3.     public class GameController : ITickable,IInitializable,IDisposable
    4.     {
    5.         [Inject] public OnGameInitializedSignal _signal;
    6.  
    7.         public void Initialize()
    8.         {
    9.             _signal.Listen(OnSignal);
    10.             _signal.Fire();
    11.         }
    12.  
    13.         private void OnSignal()
    14.         {
    15.             Debug.Log("OnSignal");
    16.         }
    17.  
    18.         public void Tick()
    19.         {
    20.            
    21.         }
    22.  
    23.         public void Dispose()
    24.         {
    25.             _signal.Unlisten(OnSignal);
    26.         }
    27.     }
    28. }
    To be honest, I don't see anything wrong with it? Can you help?
     
  50. eventropy

    eventropy

    Joined:
    Oct 4, 2012
    Posts:
    248
    Nope, it looks fine. Can you show me the installer with signal and game controller?