We have decided to repackage our services into a series of IPlugin plugins that are then added as plugins in the appHost.Configure() as a way to reuse the services in other AppHosts.
We used to register all the dependencies of the services in the appHost.Configure(), but now simply do this:
public override void Configure(Container container)
{
base.Configure(container);
Plugins.Add(new NewService());
}
and we moved all our container registration stuff to our plugin, like this:
public void Register(IAppHost appHost)
{
//register dependencies here
container.RegisterAutoWiredAs<MyType, IMyType>().ReusedWithin(ReuseScope.Request);
//etc.
}
The assumption was that the net result in the container would be the same.
However, at runtime, I see that IPlugin.Register() of my plugin is not called until after appHost.OnAfterInit() which is too late for us.
We need the code that we used to have in appHost.Configure() and that is now in IPlugin.Register() to run at or about the same time.
I then noticed from http://docs.servicestack.net/plugins that there is the IPreInitPlugin interface that may offer an earlier chance to do our container registeration, so now I tried:
public void Configure(IAppHost appHost)
{
//register dependencies here
container.RegisterAutoWiredAs<MyType, IMyType>().ReusedWithin(ReuseScope.Request);
//etc.
}
Which looks more like what we want, and indeed at runtime, this code is run immediately after appHost.Configure().
However, i now get this exception:
[InvalidOperationException: Collection was modified; enumeration operation may not execute.]
System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) +56
System.Collections.Generic.Enumerator.MoveNextRare() +14634898
ServiceStack.ServiceStackHost.ConfigurePlugins() +163
ServiceStack.ServiceStackHost.Init() +811
Crib.Services.Identity.Global.Application_Start(Object sender, EventArgs e) in C:\Projects\github\mindkin\crib\src\Crib.Api.Identity\Global.asax.cs:15
[HttpException (0x80004005): Collection was modified; enumeration operation may not execute.]
System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +520
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +176
System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +165
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +267
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +341
[HttpException (0x80004005): Collection was modified; enumeration operation may not execute.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +523
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +107
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +688
I’m not sure which collection is modified. I don’t think I am doing any of that in my plugin.
However, I am adding and removing plugins elsewhere in my appHost.Configure().
On a side-note I’d really recommend avoiding RequestScope, it’s tied to a Request Context and if your resources are pooled (like most of ServiceStack providers, e.g. OrmLite/Redis) then it’s worse for performance as it keeps resources open for longer. I never use it, if your dependency is ThreadSafe use AddSingleton if it’s not use AddTransient.