VContainer icon indicating copy to clipboard operation
VContainer copied to clipboard

"ValueFactory attempted to access the Value property of this instance" When resolving inside an async method.

Open lucasmontec opened this issue 2 years ago • 5 comments

I got an exception while calling a resolve of an interface inside a UniTask async method.

Resolve called:

Container.Resolve<IEnumerable<IRequestInstanceOnContainerBuilt>>();

The class that implements the interface:

[UsedImplicitly]
    public class StatsApplier : IRequestInstanceOnContainerBuilt, IStatsChangedListener

Class registration:

public override void Configure(IContainerBuilder builder)
{
            builder.Register<StatsApplier>(Lifetime.Singleton)
                .As<IRequestInstanceOnContainerBuilt>()
                .As<IStatsChangedListener>();

Exception:

InvalidOperationException: ValueFactory attempted to access the Value property of this instance.
System.Lazy`1[T].ViaFactory (System.Threading.LazyThreadSafetyMode mode) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
System.Lazy`1[T].ExecutionAndPublication (System.LazyHelper executionAndPublication, System.Boolean useDefaultConstructor) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
System.Lazy`1[T].CreateValue () (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
System.Lazy`1[T].get_Value () (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
VContainer.ScopedContainer.CreateTrackedInstance (VContainer.Registration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@80086eec36/Runtime/Container.cs:138)
VContainer.ScopedContainer.ResolveCore (VContainer.Registration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@80086eec36/Runtime/Container.cs:122)
VContainer.Diagnostics.DiagnosticsCollector.TraceResolve (VContainer.Registration registration, System.Func`2[T,TResult] resolving) (at Library/PackageCache/jp.hadashikick.vcontainer@80086eec36/Runtime/Diagnostics/DiagnosticsCollector.cs:72)
VContainer.ScopedContainer.Resolve (VContainer.Registration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@80086eec36/Runtime/Container.cs:79)
VContainer.Internal.CollectionInstanceProvider.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@80086eec36/Runtime/Internal/InstanceProviders/CollectionInstanceProvider.cs:69)
VContainer.Registration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@80086eec36/Runtime/Registration.cs:33)

lucasmontec avatar Sep 13 '22 01:09 lucasmontec

This happened on a child container.

lucasmontec avatar Sep 13 '22 01:09 lucasmontec

The issue happens because the lazy was created with a security feature for threads: image

lucasmontec avatar Sep 13 '22 01:09 lucasmontec

After inspecting what was happening better, it seems it is a circular dependency issue. I have this interface: IRequestInstanceOnContainerBuilt It allows me to flag objects as objects that I want an instance when the container is created. I have a top level container and a scoped child container. Both have IRequestInstanceOnContainerBuilt concrete instances. The top component creates the instances of the classes that implement this interface by calling Container.Resolve<IEnumerable<IRequestInstanceOnContainerBuilt>>(); This causes the container to resolve all concrete classes that have that. Then the child container is created and calls the same resolve. This causes this exception. I still don't get what becomes a recursive call, but it does, as per the value factory comment on the C# source code for the lazy object under ExecutionAndPublication.

lucasmontec avatar Sep 13 '22 02:09 lucasmontec

Found the circular dependency: StatApplier (which is a IStatsChangedListener) asks for a IStatsProvider which is a ModificationStatsProvider. Then ModificationStatsProvider asks for a list of IEnumerable<IStatModificationsProvider>. The only IStatModificationsProvider existing yet is the ArtifactInventory, which to be created asks for a IEnumerable<IStatsChangedListener> statsChangedListeners, which will ask for a StatApplier inside the stat applier creation.

lucasmontec avatar Sep 13 '22 02:09 lucasmontec

The circular dependency problem need more clear exception message.

SettingDust avatar May 21 '23 07:05 SettingDust