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

Trying to use MDI options pattern in both parent and child container throws exception #82

Open
esardaya opened this issue Aug 6, 2020 · 0 comments
Assignees
Labels

Comments

@esardaya
Copy link

esardaya commented Aug 6, 2020

Hello,

I have a situation where I need to be able to use a IHttpClientFactory that has been configured globally (in the root container) in my application, and additional factories that are configured on each web host that my application creates.
To this end I've been using a root unity container and then using the MDI extension to also use it for each web host I create so that they can share some common configuration.
Unfortunately, I noticed some strange behavior where only the configuration set up in the global IHttpClientFactory would be available when trying to use it in middleware, etc.
After some debugging, it looked like an issue where the various ConfigureNamedOptions<HttpClientFactoryOptions> instances added by the UseHttpClient method weren't merged together properly when added from both a parent and child container.

I wrote a small unit test in order to specifically test how the options pattern behaves when using named options on both a parent and child container to see if that was indeed the case.
Unfortunately, when running the test I encountered an unexpected exception when building the service provider in the child container:
Object reference not set to an instance of an object.
Error in: RegisterType<IOptions`1,OptionsManager`1>( 'ALL', Lifetime:InjectionPerContainer)

Unit Test:

namespace UnityRepro
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Microsoft.Extensions.DependencyInjection;
    using System.Collections.Generic;
    using Microsoft.Extensions.Options;
    using Unity;
    using Unity.Microsoft.DependencyInjection;

    [TestClass]
    public class UnityMdiOptionsTest
    {
        [TestMethod]
        public void TestOptions()
        {
            const string name = "myoptions";
            IUnityContainer parent = new UnityContainer();
            IServiceCollection parentServices = new ServiceCollection();
            parentServices.AddOptions();
            parentServices.Configure<MyOptions>(name, opt => opt.Values.Add("parent"));
            parentServices.BuildServiceProvider(parent);

            IOptionsMonitor<MyOptions> parentMonitor = parent.Resolve<IOptionsMonitor<MyOptions>>();
            MyOptions parentOptions = parentMonitor.Get(name);
            Assert.IsTrue(parentOptions.Values.Contains("parent"));

            using IUnityContainer child = parent.CreateChildContainer();
            IServiceCollection childServices = new ServiceCollection();
            childServices.AddOptions();
            childServices.Configure<MyOptions>(name, opt => opt.Values.Add("child"));
            childServices.BuildServiceProvider(child); // this line throws

            IOptionsMonitor<MyOptions> childMonitor = child.Resolve<IOptionsMonitor<MyOptions>>();
            MyOptions childOptions = childMonitor.Get(name);
            Assert.IsTrue(childOptions.Values.Contains("child"));
        }

        private class MyOptions
        {
            public List<string> Values { get; } = new List<string>();
        }
    }
}

The exception is thrown when building the service provider using the child container: childServices.BuildServiceProvider(child);

Am I doing something wrong here? It seems to me that this should just work, but perhaps this is an unsupported scenario.

@ENikS ENikS self-assigned this Aug 19, 2020
@ENikS ENikS added the Bug 🐛 label Aug 19, 2020
@ENikS ENikS modified the milestone: 5.11.0 Aug 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants