Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NestedContainer and Outer Module Event behaviour #933

Closed
Yakyyaky opened this issue Sep 10, 2018 · 1 comment
Closed

NestedContainer and Outer Module Event behaviour #933

Yakyyaky opened this issue Sep 10, 2018 · 1 comment

Comments

@Yakyyaky
Copy link

using System.Collections.Generic;
using System.Linq;
using Autofac;
using Autofac.Core;

namespace AutofacResolveWeirdness
{
    class Program
    {
        static void Main(string[] args)
        {
            var builder = new ContainerBuilder();
            builder.RegisterModule<PreparingModule>();
            var container = builder.Build();

            using (var nestedContainer = container.BeginLifetimeScope(containerBuilder =>
                {
                    // note the instance per lifetime
                    containerBuilder.RegisterType<Foo>().InstancePerLifetimeScope();
                }))
            {
                try
                {
                    nestedContainer.Resolve<Foo>();
                }
                catch (DependencyResolutionException e)
                {
                    // it fails and enters here.
                }

                var nestedFoos = nestedContainer.Resolve<IEnumerable<Foo>>();
                // the nested container has successfully resolved a list of Foo!!
                // It is now in the container because it is instance per lifetime.
                var foo = nestedContainer.Resolve<Foo>();
                // success!
            }

            using (var nestedContainer = container.BeginLifetimeScope(containerBuilder =>
                {
                    // instance per dependency
                    containerBuilder.RegisterType<Foo>();
                }))
            {
                try
                {
                    nestedContainer.Resolve<Foo>();
                }
                catch (DependencyResolutionException e)
                {
                    // it fails and enters here.
                }

                // the following works, as shown in the previous container, it scan the global scope.
                var nestedFoos = nestedContainer.Resolve<IEnumerable<Foo>>();

                try
                {
                    // as it is instance per dependency, the following resolution will continue to fail.
                    nestedContainer.Resolve<Foo>();
                }
                catch (DependencyResolutionException e)
                {
                    // it continues to fails and enters here.
                }
            }
        }
    }

    public class PreparingModule : Module
    {
        protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
        {
            registration.Preparing += OnRegistrationPreparing;
        }

        private void OnRegistrationPreparing(object sender, PreparingEventArgs e)
        {
            var barParameter = new ResolvedParameter(
                (info, context) => info.ParameterType == typeof(Bar),
                (info, context) => new Bar());

            e.Parameters = e.Parameters.Union(new[] {barParameter});
        }
    }

    public class Foo
    {
        public Foo(Bar bar) { }
    }

    public class Bar { }
}

I'm not sure whether this is a bug or not, however it did catch me out and was wondering why some objects were able to be injected with Bar while other couldn't until I narrowed down the problem to the above situation.

Should the nested container be able to resolve Foo object to begin with??
The nested container don't appear to make use of PreparingModule in certain circumstances. ie Resolve() vs Resolve<IEnumerable>()
I am expecting a more consistent behaviour as in, they either both fails or both succeeds.

As a workaround, I am currently explicitly registering PreparingModule again in the nested scope and all is consistent and resolves in every case as one would expect.

@tillig
Copy link
Member

tillig commented Sep 10, 2018

This appears to be a duplicate of #218 - module AttachToComponentRegistration handlers don't know anything about new child lifetime scopes. That would cause the observed issue. No resolution at this time; we're open to pull requests.

@tillig tillig closed this as completed Sep 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants