Giter VIP home page Giter VIP logo

zenject's People

Contributors

altunsercan avatar bitbutter avatar bvance avatar cooloon avatar extrys avatar foobraco avatar hdanilo avatar jamesdaviesss avatar jamjardavies avatar jdessart-mt avatar jhett12321 avatar johnlcox avatar kruncher avatar marsermd avatar mathijs-bakker avatar movestill avatar mysticfall avatar nezz avatar paulpach avatar rtaylornc avatar sbergen avatar shreyasd avatar soren025 avatar ssannandeji avatar suzdalnitski avatar svermeulen avatar thematthopkins avatar tsgcpp avatar yacuzo avatar zeljkokalezic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zenject's Issues

ParentContracts within SceneTests

Hey,

I have a Main scene in which an additional Environment scene is loaded inside the initialize function of a script. The Main scene has Main set as Contract name whereas the Environment scene references the Main scene as parent contract. This works well when playing the scene in play mode.

Now, I am writing a Scene test using the Zenject SceneTestFixture class that loads the Main scene. However, in that case I get the following Exception as soon as the Environment scene is loaded:

ZenjectException: SceneContext on object SceneContext of scene Environment requires at least one of contracts 'Main', but none of the loaded SceneContexts implements that contract.

I think this is a bug.

Reflection Baking fails on nested class inside a DLL

I have a DLL with some basic models that uses the Factory and MemoryPool from Zenject.

    public class Player : IPlayer
    {
        public int Id { get; set; }
        public class Pool : MemoryPool<Player> { }
    }

When I run the reflection baking on the DLL, I get the following error:
Could not find actual type for type 'Player/Pool', skipping

If I declared the pool as a non-nested class, there is no error message.

I am not sure if I am doing something incorrectly or maybe it is simply not possible to make nested class in the DLL for reflection baking.

Unable to set parent back to original while object is marked to be destroyed.[Pooling]

Below is the stack trace.
This happens when a pooled object is reparent during it's spawn life cycle and when Dispose is called on Mono-behaviour i am Despawning this from the pool. In Example Space Game 2 there is no error thrown but error is thrown in my game. Im unable to fix this. Is it just luck that its fine in example but not in mine or have done something wrong when following the architecture of example... Im wondering..

Cannot set the parent of the GameObject 'PlayerSquad(Clone)' while it is being destroyed.
UnityEngine.Transform:SetParent(Transform, Boolean)
Zenject.MonoPoolableMemoryPool3:OnDespawned(PlayerSquadFacade) (at Assets/Plugins/Zenject/Source/Factories/Pooling/MonoPoolableMemoryPool.cs:116) Zenject.MemoryPoolBase1:Despawn(PlayerSquadFacade) (at Assets/Plugins/Zenject/Source/Factories/Pooling/MemoryPoolBase.cs:134)
Zenject.MemoryPoolBase`1:Zenject.IMemoryPool.Despawn(Object) (at Assets/Plugins/Zenject/Source/Factories/Pooling/MemoryPoolBase.cs:115)
EarthArena.WorldEntities.PlayerSquadFacade:Dispose() (at Assets/Scripts/WorldGameEntities/Concretions/PlayerSquad/PlayerSquadFacade.cs:50)
Zenject.DisposableManager:Dispose() (at Assets/Plugins/Zenject/Source/Runtime/DisposableManager.cs:122)
Zenject.MonoKernel:OnDestroy() (at Assets/Plugins/Zenject/Source/Runtime/Kernels/MonoKernel.cs:77)

Zenject is not really thread safe

The code bellow will fail in a multi-threaded application. As you can see, there are two different locks to access the _typeInfo dictionary, one to TryGetValue and the other to Add.
This will raise an exception when two threads pass the first lock and both try to add the type info into the dictionary.
Locally I've fixed this by making only one big lock, encapsulating all the code from TryGetValue to Add, but I'm not sure if this is the best approach as I'm not familiar with the rest of the library.

https://github.com/svermeulen/Extenject/blob/32d175f28450530cd160f866d970af07487c822f/UnityProject/Assets/Plugins/Zenject/Source/Util/TypeAnalyzer.cs#L117-L152

the class Signal missed

I updated my project to 2018.3 and the zenject doesn't work anymore, so I deleted it fully and install this Extenject, I found the Zenject. Signal class missed which I used before.

PlaceholderFactory likes to pretend it doesn't exist at times.

I've had this problem for a few months now, and it seems random for when it happens.

It seems that PlaceholderFactory likes to act like it isn't a class which with give errors saying it cannot be found. This only happens in VS as Unity will compile and run, but VS will not compile which will lead to me not being able to debug.

It seems like PlaceholderFactory is the only class that gives trouble as other classes in Zenject - even in the same file - will not give any errors. I've fixed this by exiting Unity, deleting all my sln/vsprog files, and running Unity again. This will work for a time until the problem randomly comes back.

I'm free to dig deeper into this, but I'm not sure where to start as it is very random.

Looking for correct approach for convention-based bindings

I'm adjusting my code to Extenject after updating from 2017 version of Zenject (passed Zenject 6+ version boundary).

Until now I didn't have problems with convetion-based binding of interfaces to classes that implement them:

Container.Bind(x => x.AllInterfaces().Where( some exclusions)
.To(x => x.AllNonAbstractClasses()
                    .InNamespaces( a few of my namespaces here )
.AsSingle();

Even though that this construction is smartly matching the types for bindings, I noticed that it also creates entries for _boundSingletons set in Zenject for implementations that don't have any matching interfaces.
For example I have TilemapGenerator class that doesn't derive from nor implement anything. Apart from code below I define the following binding:
Container.Bind<TilemapGenerator>().ToSelf().AsSingle();
This makes me get the following error when trying to run the game:
ZenjectException: Assert hit! Attempted to use AsSingle multiple times for type 'TilemapGenerator'. As of Zenject 6+, AsSingle as can no longer be used for the same type across different bindings.
According to suggestion in the docs, I replaced AsSingle() with FromResolve(), but that makes my Unity editor crash without even opening UnityCrashHandler.
For now I'm bypassing the problem by adding exclusions in code snippet 1. for types like my TilemapGenerator, so that I can use AsSingle() in code snippet 2.

I'm looking for suggestions what can be done to avoid my pain. I think that Zenject shouldn't add entries to _boundSingletons dictionary for types that don't have matching interfaces, but maybe there is some technical reason behind that.

Reflection baking error with built-in Unity package

After upgrading to Unity 2019.2 there is a built-in package for the Jetbrains Rider IDE. This package produces an error in the reflection baking while building:

ArgumentException: Invalid path
System.IO.Path.GetDirectoryName (System.String path) (at <a8ed250850854b439cedc18931a314fe>:0)
Zenject.ReflectionBaking.UnityAssemblyResolver..ctor () (at Assets/Plugins/Zenject/OptionalExtras/ReflectionBaking/Unity/UnityAssemblyResolver.cs:34)
Zenject.ReflectionBaking.ReflectionBakingBuildObserver.TryWeaveAssembly (System.String assemblyAssetPath) (at Assets/Plugins/Zenject/OptionalExtras/ReflectionBaking/Unity/ReflectionBakingBuildObserver.cs:65)
Zenject.ReflectionBaking.ReflectionBakingBuildObserver.OnAssemblyCompiled (System.String assemblyAssetPath, UnityEditor.Compilation.CompilerMessage[] messages) (at Assets/Plugins/Zenject/OptionalExtras/ReflectionBaking/Unity/ReflectionBakingBuildObserver.cs:37)
UnityEditor.Compilation.CompilationPipeline.<SubscribeToEvents>m__3 (System.String assemblyPath, UnityEditor.Compilation.CompilerMessage[] messages) (at C:/buildslave/unity/build/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs:179)
UnityEditor.BuildPipeline:BuildPlayer(BuildPlayerOptions)

The problem is that assemblies[i].Location returns an empty string.
I am not sure if this is a problem with the package or with Zenject. But the Rider package is editor only so it should probably not be included in the reflection baking process.

Unity: 2019.2.5f
Extenject/Zenject: 9.0.0
Workaround: In UnityAssemblyResolver.cs add a Try-Catch around AddSearchDirectory(Path.GetDirectoryName(assemblies[i].Location));

Using PreInstall/PostInstall/PreResolve/PostResolve in the ProjectContext

I can't use methods PreInstall/PostInstall/PreResolve/PostResolve from the ProjectContext.
I want to make some sort of loading menu, and trying to catch event PostResolve of the ProjectContext instance. But unfortunately it can't be done, because this actions called when I call Instance method and they will never fire.

void Main()
{
	ProjectContext.Instance.PostResolve += OnPostResolved;
}

MediatR configuration

Hey, how would MediatR Container configuration look for Extenject? I lookned into Ninject example (as I recall Zenject/Extenject) were based on it but it doesnt really help much.

Circular Dependency with GameObjectContext

Hello.

There is a problem with circular dependencies between a Subcontainer in a GameObjectContext and a type in the scene context
Main -> Foo (Main in GameObjectContext)
Foo-> Main (Foo in SceneContext)
In older versions, this caused that the GameObjectContext to be instantiated several times.

I have seen that now this is prevented by SubContainerCreatorCached._isLookingUp.

But I think the real issue is here:

public DiContainer CreateSubContainer(List<TypeValuePair> args, InjectContext context)
{
		if (_subContainer == null) // <======HERE
		{
			Assert.That(!_isLookingUp,
				"Found unresolvable circular dependency when looking up sub container!  Object graph:\n {0}", context.GetObjectGraphString());
			_isLookingUp = true;

			 // <===== AND HERE===========>
			_subContainer = _subCreator.CreateSubContainer(new List<TypeValuePair>(), context);

			_isLookingUp = false;

			Assert.IsNotNull(_subContainer);
		}

		return _subContainer;
}

_subCreator.CreateSubContainer has two parts, the creation and the injection, but the _subContainer reference is got after the injection, so

  1. Resolve Main. We are in CreateSubContainer.
  2. Instantiate GameobjectContext
  3. To Resolve Main, we have to resolve Foo
  4. To Resolve Foo, we have to resolve Main (circular dependency)
  5. Resolve Main. We are in CreateSubContainer again
  6. Because we still are inside the flow of the first resolve main, CreateSubContainer hasn't finish and _ subContainer is still null
  7. if (_subContainer == null) returns true
  8. In older versions, other GameobjectContext is instantiated twice. In the new versions, a exception is throw.

I think a solution to this could be to split CreateSubContainer in two parts.
The first part would be to instantiate the gameobject context, create a subcontainer, set it to the gameobject context and get the reference in SubContainerCreatorCached.
After this, we inject the gameobject context. This way, if we enter again in CreateSubContainer because of a circular dependency, _subContainer is no longer null
I have done a very dirty prototype just to illustrate what I mean.
What do you think?

Thank you

public DiContainer CreateSubContainer(List<TypeValuePair> args, InjectContext context)
{
		if (_subContainer == null)
		{
			SubContainerCreatorByNewPrefab creatorByPrefab = (SubContainerCreatorByNewPrefab)_subCreator;
			DiContainer sub = null;
			GameObjectContext goContext = null;
			creatorByPrefab.CreateRawSubContainer(new List<TypeValuePair>(), out sub, out goContext);
			_subContainer = sub;
			creatorByPrefab.InjectSubcontainer(goContext);

			Assert.IsNotNull(_subContainer);
		}

		return _subContainer;
	}
}
        public void CreateRawSubContainer(List<TypeValuePair> args, out DiContainer subcontainer, out GameObjectContext context)
        {
            Assert.That(args.IsEmpty());
            Object prefab = _prefabProvider.GetPrefab();

            bool shouldMakeActive;
            GameObject instance = _container.CreateAndParentPrefab(prefab, _gameObjectBindInfo, null, out shouldMakeActive);
            instance.SetActive(shouldMakeActive);
            context = instance.GetComponent<GameObjectContext>();
            context.SetContainerForCircularDependencyWorkarround(_container.CreateSubContainer());
            subcontainer = context.Container;

        }

        public void InjectSubcontainer(GameObjectContext context)
        {
            _container.InjectGameObject(context.gameObject);
        }

LazyInject should be a struct

AFAICT there is no reason for this to be a class. The four fields could easily be stored inline, and there's no reason to pass it around.

One usability benefit to this change would be to eliminate this kind of error:

[InjectField]
private LazyInject<MissionCameraCM> _missionCamera;

// ...

// Should be `_missionCamera.Value == null`!
if (_missionCamera != null) ...

Support for editorscenemanager

We're having some trouble with creating integration tests. We're trying to load a scene using editorscenemanager but Zenject doesn't call the installers on scene load

Declaring Factory for Object which doesn't have all its dependencies yet

Hey, I have a specific situation where I have a state machine which I want to be global and scene independent. I want to be able to create new instances of states, states can be scene-dependent (such as a 'combat encounter state') and these scene-dependent states will have dependencies which exist only in that scene (such as 'enemies in the combat encounter'.)

Because I want to create new state objects, I have factories set up for each state class, and contained in a global state factory class which the state machine object has a dependency on. However because this factory class is bound in the start scene, and therefore in a different context than the combat encounter scene, none of the scene-specific bindings are bound correctly when I try to create an instance of the combat encounter state.

Here's a simple example with all the state machine complexity stripped out:

I have an empty MonoBehaviour, ObjectInGameScene, and a class ObjectWithDependency:

public class ObjectWithDependency
{
    private readonly ObjectInGameScene m_object;

    public ObjectWithDependency(ObjectInGameScene objectInGameScene)
    {
        m_object = objectInGameScene;

        Debug.Log("Created a dependency object. Object is null: " + (m_object == null), m_object);
    }

    public class Factory : PlaceholderFactory<ObjectWithDependency>
    {

    }
}

I have a TestFactoryContainer class which just has a dependency on this object's factory:

public class TestFactoryContainer
{
    private readonly ObjectWithDependency.Factory m_factory;

    public TestFactoryContainer(ObjectWithDependency.Factory factory)
    {
        m_factory = factory;
    }

    public void Spawn()
    {
        m_factory.Create();
    }
}

My scenes are set up so that one scene, Start, loads the other Game. Start contains the TestFactoryContainer class whereas the actual ObjectInGameScene object exists in Game. Usually I try binding the factory and factory container in an installer in the start scene, and binding the actual object in the game scene, but unsurprisingly this results in the following error:

ZenjectException: Unable to resolve 'ObjectInGameScene' while building object with type 'ObjectWithDependency'. Object graph:
ObjectWithDependency

because the ObjectWithDependency and the factory classes don't share a Container. I understand that the solution might involve using scene parenting or scene decorator contexts but I've been unable to get either to work. Or maybe this entire approach to using Zenject is flawed.

Unity Addressable Assets

During installation, we have a number of prefabs that are installed in the scene context. The problem with referencing prefabs in the scene is any assets that are referenced are included in the final build regardless of whether they are marked to be in an asset bundle or not. Ideally, we do not want to have any references to prefabs in the scene but still want to be able to install it somehow. Unity addresses the prefab reference with addressable assets which is still a preview package. Are there any plans to support binding from addressable assets? Does Extenject support something similar currently that we could utilize with just asset bundles?

[FEATURE REQUEST] Asynchronous Injection

Hi :)

Would it be possible to create a mechanism to inject asynchronously?
Trying to use Zenject in a Sever project where dependencies are bound to a DB result.

Signal Handler inside the listener class

Hi there,

I'm a newbie learning extenject and have question regarding signals. Lambda's usually create garbages based on my limited knowledge and looks ugly.

Usually we write listener like this
Container.BindSignal<UserJoinedSignal>() .ToMethod<Greeter>(x => x.SayHello).FromResolve();

I'm looking for something which doenst require a lambda and can be passed to listener class itself.
For example
Container.BindSignal<UserJoinedSignal>() .ToMethod<Greeter>().FromResolve();
GreeeterClass for example can implement something like IUserJoinedSignal which implements
OnEventReceive(UserJoinedSignal)

Thanks

Memory Pool not thread safe ?

I have been using the Factory, Pool and Dispose pattern described in the Memory Pool documentation along with parallel tasks.
Using StaticMemoryPoolRegistry to observe the activity, I noticed that my items are not properly returned. At first I thought there was some issue within my code.

I am running with ZEN_MULTITHREADING and ZEN_INTERNAL_NO_POOLS.
From what I can tell MemoryPool and MemoryPoolBase do not contain any thread safety.

Please check the code below
ZenjectMultithreadTests.txt
Depending on the number of tasks run, either not all instances are returned to the pool or the same instance is spawned multiple times.

I am no expert in using Task in C# so it is possible I am doing something that is not allowed.

[Performance] GetRootGameObjects improvements

Currently due to an older bug, root objects are gotten with workaround. After 2017.2 scene.GetRootGameObjects is working. Reference forum post

We tested on our game 2017.4.30 and 2018.4.10 it's working perfectly fine. Can we add something like that?

#if UNITY_2017_2_OR_NEWER
                return scene.GetRootGameObjects()
                    .Where(x => x.GetComponent<ProjectContext>() == null);
#endif

Binding through FromComponentInNewPrefab() Does not work.

I am trying to bind a MonoBehaviour on a prefab through FromComponentInNewPrefab() in a Scenecontext. The prefab I am Instantiating already contains the MonoBehaviour I am binding. But it doesn't work. then I thought something might be wrong with the prefab then I tried FromNewComponentOnNewGameObject() it also didn't work.

Signal handler Decorator wraps itself

Hi,

I am implementing a solution similar to MediatR but based on Signals. Basically for every declared Signal type an implementation of

    public interface ISignalHandler<TSignal>
    {
        void Handle(TSignal signal);
    }

must be provided. The catch is that there can also be a Decorator for this handler (added logging, caching etc.) that forwards to the final Handler implementation. Currently however for some reason for a declared Handler and a Decorator, it gets wrapped twice resulting in the Decorator<Decorator<Handler>> structure (instead of Decorator<Handler> that is).

Minimal reproduction project uploaded here:

https://github.com/slimshader/ZenjectSignalHandlerDecorator

Baking Issues

Hey @svermeulen sorry to bother you with this. But I am still struggling with those baking issues since 8.0.1: https://github.com/modesttree/Zenject/issues/603

I am now using namespace pattern ^ and I tried checking All generated Assemblies and still see some types not being found in the baking data like:

LayoutGroup
GraphicRaycaster
TMP_InputField
...

Actually all these types I don't need Zenject to Inject. Is there maybe a way to annotate a field to be ignored in the Injection phase to? Something like [NoInject]?

I am on Unity 2018.3.4.1f1

Delayed project context binding

I have some branching logic that, depending on the return value from a server call either injects x or y. I would like to inject these into the project context as they need to persist between scene loads. I've mostly got this working by

  • having a scene that performs the minimum setup for the project and calls the server endpoint to get the result required for the branch and store it
  • Load a second scene that has a MonoInstaller like this
public class ServerSelectInstaller : MonoInstaller<ServerSelectInstaller>
	{
		public override void InstallBindings()
		{
			var selector = Container.Resolve<ServerChoiceService>();
			Debug.Assert(selector.ServerChoiceMade);
			if ( selector.UseLegacy )
			{
				LegacyInstaller.Install(ProjectContext.Instance.Container);
			}
			else
			{
				ModernInstaller.Install(ProjectContext.Instance.Container);
			}
                        // other bindings that require the above to be resolved first
			DelayedProjectInstaller.Install(ProjectContext.Instance.Container);
		}
	}

This mostly works but the Initialize method is not called for any class that implements IInitializable because the ProjectContext has already initialized.
Am I going about this in the wrong way? Is there a correct approach to this? I've looked at the sub-container documentation but I'm not sure if it helps me here. The code is to handle a server migration we're doing. We want to be able to switch from server A to server B which have a different API signature without having to support two clients. This seems like it should be possible with dependency injection as all my API endpoints used throughout the app call an interface with two different implementations of that interface depending on which server we're using.

[Suggestion] Create extension using Microsoft.Extensions.DependencyInjection.Abstractions

It would be nice if we could create an Adaptor or Extension for Extenject that extends the Microsoft.Extensions.DependencyInjection.Abstractions lib. That way, we can rely on an abstracted DIContainer rather than binding our game projects directly to Extenject. However, I appreciate there's a lot of Unity specific things in Extenject.

Other DI's have done this, so I'm sure it's possible. Please see: https://github.com/aspnet/Extensions/tree/master/src/DependencyInjection

Exception when objects injected more than once because of misuse

Hello,

In our project, there are objects that are injected several times, not because of extenject, but because of misuse.
I realized of that because there is an object that creates a dictionary in the injection, so the keys are duplicated on the second time the object is injected.

I think it could be nice to throw an exception, warning, or something when this happens, to prevent this misuse.
I know it can be expensive, so maybe it could be configurable in some kind of zenject settings

In DiContainer, for example:


if(injectedObjects.Contains(injectable)
{
  throw new ZenjectException(injectable + " already injected. Please check");
}
 method.Action(injectable, paramValues);
injectedObjects.add(injectable)
}

Zenject is incompatible with UNet?

Seems like DI is not suitable for Unity Networking / Mirror at all.
It has NetworkManager which needs a player prefab reference. But if I spawn a player through DI bindings, I obviously can't put it into Network Manager slot.

Testable Factory

Hi there,
I recently tried to setup a factory for an interface. This factory should be able to create an object inheriting the interface. I planned to give the exact type while binding the factory in the installer.

I struggled though setting up a mock for the interface and binding the factory and injecting it.

Could you give me an example in how to do that? I hope you understand what I'm tryin to do.
Please add this also to your documentation.

How can ZenjectBinding bind a component to the Project Context?

ZenjectBinding works when bound in a SceneContext, but does not get bound to a ProjectContext when I load Scenes Additively via ZenjectSceneLoader.

Is there something that I'm missing or is this feature not implemented? If not, what would be the suggested methodology?

Exception: Multiple instances of SignalBus found

Hello!

I posted the issue we have also in the Zenject repo (ssannandeji#656) but it can be reproduced with Extenject 8.0.1 as well.
When loading 3 scenes each with a SceneContext and parented using Contract Names and the SignalBus installed in the first scene we get the following exception when the third scene is loaded:

ZenjectException: Found multiple matches when only one was expected for type 'SignalBus' while building object with type 'SignalBus'. Object graph:
SceneKernel
DisposableManager
SignalBus

The second and third scene each install a component which gets the SignalBus injected.
I have created a simple project to reproduce the error. I'm on Windows 10 with Unity 2018.4.3f1 with Extenject 8.0.1.
To run the project open it in Unity and add '[email protected]
' (the GameSignalsInstaller from the sample game is used in the test project). The main scene is called 'SignalBusIssueScene1' located in the folder 'SignalBusIssue'.
I also attached the output log from the build so you can see the whole stack trace of the exception.
ZenjectSignalBusIssueProject.zip
output_log.txt

NSubstitute warnings with upm

I imported extenject 9.1.0 using upm, and I get the following warnings:

A meta data file (.meta) exists but its asset 'Packages/com.svermeulen.extenject/OptionalExtras/TestFramework/Editor/AutoSubstitute/__MACOSX/AutoSubstitute/NSubstitute' can't be found. When moving or deleting files outside of Unity, please ensure that the corresponding .meta file is moved or deleted along with it.

Couldn't delete Packages/com.svermeulen.extenject/OptionalExtras/TestFramework/Editor/AutoSubstitute/__MACOSX/AutoSubstitute/NSubstitute.meta because it's in an immutable folder.

Awake and OnEnable running before Construct with DecoratorSceneContext

Hello and glad to have you back! It was starting to become scary. :)

The package in the attachment contains everything to reproduce the bug. Open and run the 'Decorator Scene'.

To quickly describe the problem, there are two scenes, Main and Decorator. Main has a SceneContext while the Decorator has a DecoratorSceneContext. Both of these scenes have MonoBehaviour classes in them (MainSceneMono and DecoratorSceneMono) which expect dependencies from the other scene. The DecoratorSceneMono also has an Awake method which runs the 'SayHello()' method of the Foo class, which is bound in the Main Scene. Upon running the scene, the Awake method of the DecoratorSceneMono executes before the [Inject] Construct() method. Tests with Start() and OnEnable() have shown this execution order:

Awake() -> OnEnable() -> [Inject] Construct() -> Start()

DecoratorContext.zip

RunnableContext.CreateComponent<T> does not work on GameObjectContext

I think this happens cause GameObjectContext Initialize moved from Awake to Construct method which needs to inject DIContainer parentContainer.

so, now I have two choices - make subContainer manually and install installer, or call Construct method manually.

any suggested ideas?

Signals Pooling?

Hi there,

As im still learning so i might be asking wrong questions without knowing the whole background, so please bear with me.

I noticed that when we fire signals we create a new instance of the event class every time which means there seems to be no pooling involved.

Can we pool the events, is there any exmaple code there?

Thanks

Cannot Unbind/Rebind AsSingle bindings

After creating a binding as a singleton, that value cannot then be unbound/rebound via Container.Unbind() or Container.Rebind().

The following two code snippets throw the error: ZenjectException: Assert hit! Attempted to use AsSingle multiple times for type 'string'. As of Zenject 6+, AsSingle as can no longer be used for the same type across different bindings. See the upgrade guide for details.

Example 1:

Container.Bind<string>().To<string>().FromInstance("test1").AsSingle();
Container.Unbind<string>();
Container.Bind<string>().To<string>().FromInstance("test2").AsSingle();

Example 2:

Container.Bind<string>().To<string>().FromInstance("test1").AsSingle();
Container.Rebind<string>().To<string>().FromInstance("test2").AsSingle();

My use case is that I'd like to have a separate singleton instance of a class for each container. I was hoping to run the following installer in each container, so that each container has some contextual information I can use to improve logging:

IContainerInfo containerInfo = new ContainerInfo(m_Settings.ContainerName);
Container.Rebind<IContainerInfo>().To<IContainerInfo>().FromInstance(containerInfo).AsSingle();

Regression: ByNewContextPrefab<TInstaller> fails to check installer base class injectables

We are upgrading from 8c63509 (7.1.0'ish IIRC), and when doing something like

Container.BindFactory<Parameter, T, T.Factory>()
  .FromSubContainerResolve()
  .ByNewContextPrefab<DerivedInstaller>(somePrefab);

where DerivedInstaller derives from BaseInstaller<TInstaller>, which derives from MonoInstaller<BaseInstaller<TInstaller>>, and BaseInstaller gets Parameter injected, an error like

ZenjectException: Assert hit! Could not find match for argument type 'Parameter' when injecting into sub container installer 'DerivedInstaller'

will be hit both during validation and runtime.

Adding

.Concat(installerInjectables.BaseTypeInfo.AllInjectables)

after https://github.com/svermeulen/Extenject/blob/09e5557/UnityProject/Assets/Plugins/Zenject/Source/Providers/SubContainerCreators/SubContainerCreatorByNewPrefabWithParams.cs#L44
solves the issue, but I'm not sure if that's the correct place to do it.

Please find a git export with a reproduction (and symlinked submodule reference) attached:
BaseInstallerFactoryInjection.zip

Project Context - ParentNewObjectsUnderSceneContext flag missing in Editor

From what I read in the source code and in your documentation, in the Unity Editor, the Project Context component should have a flag "Parent new objects under ProjectContext". SceneContext components have this flag and the ProjectContext's don't. Is that a bug?
I tested this in Unity 2019.1.14f and Unity 2019.2.6f.

How to validate object graph as an automated test outside of Unity

I am creating an external library (that will be later used in Unity) using Extenject. I would like to check if I can successfully resolve bind objects using an automated test. Eg. I have the following:

container.Bind<TBind>().To<TTo>().AsSingle();

To test this simple graph I can just call

container.Resolve<TBind>()

and see if there is any exception thrown.

However this is getting much more complicated once using constructs like WhenInjectedInto.
Is there any out-of-the-box solution for this? Or has someone wrote their own working solution and would like to share?

I realize, that there is a Validator when using Extenject withing Unity. But I want to validate the graph without Unity.

Incorrect BindExecutionOrder Behaviour per Documentation

As per the main documentation BindExecutionOrder and it's variants are intended to set the priority for a specified type's execution order, with the following example given:

void InitExecutionOrder()
{
    // In many cases you don't need to worry about execution order,
    // however sometimes it can be important
    // If for example we wanted to ensure that AsteroidManager.Initialize
    // always gets called before GameController.Initialize (and similarly for Tick)
    // Then we could do the following:
    Container.BindExecutionOrder<AsteroidManager>(-10);
    Container.BindExecutionOrder<GameController>(-20);

    // Note that they will be disposed of in the reverse order given here
}

The indication being that AsteroidManager having a higher priority value will always be executed first/last depending on the interface type, in the case of IInitializable/ITickable AsteroidManager should be called first before GameController. What I am seeing in my own project is the opposite, and after looking into InitializableManager the following stands out:

public void Initialize()
{
    //....
    _initializables = _initializables.OrderBy(x => x.Priority).ToList();

    //....
    foreach (var initializable in _initializables)
    {
        //....
        initializable.Initializable.Initialize();
        //....
    }
}

Since the OrderBy results are ascending, this puts AsteroidManager at the end of the list (in my project a different type of course) and so it is initialized after GameController. An easy fix would be to change the OrderBy operator to OrderByDescending, and I considered making a pull-request doing just that, but I am worried about the implications of the change for projects depending on the current execution order.

The scenarios here are:

  1. The documentation and I are wrong in the assumption and the numbers are intended to be non-negative in the example given, meaning that AsteroidManager (priority +10) and GameController (priority +20) would operate as expected.
  2. Other projects using BindExecutionOrder have noticed this issue as well and disregarded the documentation, using lower numbers as 'higher priority'.

The last changes seem to go back to e639deb so I expect that at this point the accepted behaviour is that lower numbers are higher priority, but if you could clarify on this point I could put together a PR for the doc changes, and any uses in examples in the code base.

Thank you

User Error -> StackOverflow AssertHit! (999+ times)

I managed to get a very nasty error by accidentally putting a MonoInstaller in the list of PrefabInstallers (attached to SceneContext).

This is a user error, in that I just wasn't paying enough attention when I added the installer, but it did result in Unity freezing for quite a while and then printing Zenject Exception: Assert hit! 999+ times to the console.

Aside from locking Unity up for a minute or two the error message is less than obvious (especially for a beginner).

Steps to reproduce:

Add SceneContext
Create MonoInstaller
Add MonoInstaller as component of SceneContext gameobject
Add MonoInstaller to PrefabInstaller list
Run project

Without ever having touched the prefab installer before, I'm guessing this causes it to instatiate itself in an infinite loop.

I'm running Unity 2019.1.14f1 (though I doubt that matters).

Please note: This was from the asset store version of Zenject before I discovered Extenject
Update: Confirmed that this happens in v9.1.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.