Moving Services to Plugins

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.

What should be done?

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().

Have a look at how TemplatePagesFeature or ServerEventsFeature uses appHost.RegisterService() to register services.

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.