November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
In CMS 12 you should do that in the ConfigureServices method of your Startup class instead, avoiding initialization modules when possible.
Since this is an independent module for customer's system I have planned to enclose everything in the InitializationModule, but you sugessting to register evething in Startup instead?
After adding
services.AddSingleton<IObjectInstanceCache, MemoryObjectInstanceCache>();
provider moves further but now it cannot find implememtation of EPiServer.Framework.ITimeProvider.
Why all of that is not registred in existed services.AddCms()?
No idea how to get a service I have just registred without ServiceProvider. Also ServiceLocator.Current.GetService(typeof(SomeType)) returns null.
Hi L,
I believe all the services you mention are registered by the FrameworkInitialization
(EPiServer.Framework
) initalizable module.
You should specify a dependency on it in your initializable module and see if that helps.
[InitializableModule]
[ModuleDependency(typeof(FrameworkInitialization))]
public class MyInitializationModule : IConfigurableModule {}
Perhaps try to register yours in context.ConfigurationComplete event?
context.ConfigurationComplete += (o, e) =>
{
e.Services.TryAddSingleton<blah blah blah ...
};
Quan's solution should be working, the ConfigurationComplete event should be the last thing executed during configuration. However, what I don't understand is why you register the service into container and then retrieve it immediately by forcing to create a new scope of the container? Manually invoking BuildServiceProvider could lead unexpected behaviour (e.g. intensive singleton services are being re-created). If you need to reference to the instance of your class during the registration, I recommend going with manually instantiate the object
public void ConfigureContainer(ServiceConfigurationContext context)
{
context.Services.Configure<ProtectedModuleOptions>(pm => pm.Items.Add(new ModuleDetails { Name = "MyModule" }));
var someTypeInstance = new SomeType();
context.Services.AddSingleton<SomeType>(someTypeInstance);
}
As you already stated in your original post - you can register types whenever you want. However, in order to create a instance of that type - all dependencies for that instance needs to exist in the registry as well. As the name ConfigureContainer suggests - the purpose of this method is to set up the service provider (for example StructureMap registry) - nothing else. You should not use the service provider to create instances, because the service provider is not yet ready.
So, you need to move serviceProvider.GetService<SomeType>() (which creates the instance) to something that occurs later - for example ConfigurationComplete, as Quan mentioned. At this point, the service provider is ready to use.
Ok, now it seems to have sense. I was registering my services in the ConfigureContainer() method. Some of my classes had dependencies on Episerver stuff like EPiServer.DataAbstraction.ILanguageBranchRepository. Being still ConfigureContainer() method I needed to retrieve class that I registered and I was facing that problem with Epi part wasn't ready yet. Even after added
[ModuleDependency(typeof(FrameworkInitialization))]
I moved retrieving my service to Initialize() method and now I can use it to initialize what I need :)
Also that suggestion to extract services registration to the separate extension method seems a better idea than keeping it in the module.
Theory tells us that module has to be split into 2 parts: registration and usage.
That is the reason why we see services.AddSomething(); and app.UseSomething();. in our Startup.cs files.
So you should look for a way to split your module into registering your dependencies in phase #1 - configure container, and phase #2 - use those registered dependencies to carry out tasks during startup.
I was also struggling with this until I realize that I actually don't need that dependency yet - I can make use of it when everything is configured, the dependency container is built and the app is about to start.
Hi,
I'm implemeting InitializationModule
Error is `System.InvalidOperationException: No constructor for type 'EPiServer.Events.Internal.RemoteCacheSynchronization' can be instantiated using services from the service container and default values.`.
Ok, RemoteCacheSynchronization type needs some IObjectInstanceCache to instantiate, but it is module job to register it? Modules could use different caches, or what?