Search code examples
c#autofac

Autofac's `reloadOnChange` doesn't reload the configuration?


I have a simple basic configuration for Autofac , which uses JSON configuration file :

 var config = new ConfigurationBuilder();
 config.AddJsonFile("autofac.json",false,true); //notice reloadOnChange

 // Register the ConfigurationModule with Autofac.
    var module = new ConfigurationModule(config.Build());
    var builder = new ContainerBuilder();
    builder.RegisterModule(module);


 // Set the dependency resolver to be Autofac.
    _container = builder.Build();

Here is the JSON :

{
  "defaultAssembly": "AutoFacConfigFile",
  "components": [
    {
      "type": "AutoFacConfigFile.ConsoleOutput",
      "services": [
        {
          "type": "AutoFacConfigFile.IOutput"
        }
      ],
      "instanceScope": "single-instance",
      "injectProperties": true
    }
  ]
}

The ConsoleOutput writes the exact input string :

public class ConsoleOutput : IOutput
    {
        public void Write(string content)
        {
            Console.WriteLine(content);
        }
    }

However , The ConsoleOutput2 writes the exact input string + "222222222":

public class ConsoleOutput2 : IOutput
    {
        public void Write(string content)
        {
             Console.WriteLine(content+"22222222222");
        }
    }

I want to see that if I change form ConsoleOutput to ConsoleOutput2, then I'll see the different output on runtime, that's why I created a loop :

  static void Main(string[] args)
        {
            AutofacExt.InitAutofac();
            var writer = AutofacExt.GetFromFac<IOutput>();
            Get(writer).Wait();

        }

        public static async Task Get(IOutput writer)
        {
            for (int i = 0; i < 100; i++)
            {
               await Task.Delay(1000);
               writer.Write("s");
            }
        }

However, even if I change the JSON file, when the loop is running, I don't see a new response. I only see the old response :

enter image description here

Question:

Why does changing from ConsoleOutput to ConsoleOutput2 doesn't reflects the change?

I expect:

"s"
"s"
"s"
                             -- file changed and saved here --
"s2222222222"
"s2222222222"
"s2222222222"

Solution

  • Autofac doesn't provide or own the configuration builder. It's not "Autofac's reloadOnChange", it's "Microsoft.Extensions.Configuration's reloadOnChange."

    Autofac will read configuration provided in that format, however, once the container is built, that's it. There is no "tie" or anything between the container contents and the configuration after that.

    Containers are effectively immutable. Updating the container is being removed for a variety of reasons and it's these same reasons the container isn't rebuilt on configuration change.

    If you need to change the contents on configuration change, you'll need to do that in your application code.

    • Catch the event that indicates change
    • Build an all new container
    • Swap the new container out for the old container

    That's easier said than done, especially as the app is running and things may be holding references to objects resolved from the old container. That's actually a big reason this isn't supported. I have no guidance in how to accomplish that and would actively argue against it.

    Again, check out this discussion if you're interested in more on why containers are immutable.