How to do a registration in Simple Injector after a GetInstance call / Alternate solution?

c#, ioc-container, simple-injector

Solution

Simple Injector locks the container for further changes after its first use. This is an explicit design choice, which is described here. This means that you can't call `Register` after you called `GetInstance`, but there should never be a reason to do this. Or in other words, your configuration can always be rewritten in a way that you don't need this. In your case your configuration will probably look something like this:

var settingsManager = new SettingsManager(new SqlSettingManager("connStr"));

container.RegisterSingle<ISettingsManager>(settingsManager);
container.Register<ICommunicationClient, CommunicationClient>();

string url = settingsManager.GetSetting("url");
string userName = settingsManager.GetSetting("username");
string password = settingsManager.GetSetting("password");

container.Register<IServerConfiguration>(() => 
      new ServerConfiguration(url, userName, password));

There you see that `SettingsManager` is not built-up by the container. When using a DI container, you are not required to let the DI container build up every instance for you. Letting the container auto-wire instances for you is done to lower the maintenance burden of your Composition Root and makes it easier to apply cross-cutting concerns (using decorators for instance) to groups of related classes. In the case of the `SettingsManager` and `SqlSettingsManager` classes, it is very unlikely that their constructor will change that often that it will increase the maintenance burden of your Composition Root. It's therefore perfectly fine to manually create those instances once.

Problem

Consider the following example: ``` public class CommunicationClient : IClient { public CommunicationClient(IServerSettings settings) { ... } // Code } public class SettingsManager : ISettingsManager { SettingsManager(IDbSettingManager manager) // Code public IDictionary<string, string> GetSettings() { ... } } ``` Problem: While performing registrations (using `SimpleInjector`), I need to provide values that are obtained from an instance of `SetingsManager` and fill `ServerSettings` instance (concrete type for `IServerSettings`) but if I call `GetInstance<ISettingsManager>` before registering `CommunicationClient`, it gives me an error that I cannot do that Error: The container can't be changed after the first call to GetInstance, GetAllInstances and Verify.) One solution could be to inject `ISettingsManager` as a dependency to `CommunicationClient` but I really don't want to pass it as it would provide more than required information to it. EDIT: Container Registration ``` container.Register(typeof(ICommunicationClient), typeof(CommunicationClient)); ISettingsManager settingsManager = container.GetInstance<ISettingsManager>(); string url = settingsManager.GetSetting("url"); string userName = settingsManager.GetSetting("username"); string password = settingsManager.GetSetting("password"); container.Register(typeof(IServerConfiguration), () => new ServerConfiguration(url, userName, password); ``` Any suggestions/alternative solutions on how to achieve above in a cleaner way? Thanks.

Original source