I am writing a Windows service using Topshelf that should start a self hosted webapi project and a FIX service based on quickfix/n. Please consider the shortened code below, which works so far.
However there is one problem - there are now two container instances living in my application. My guts tell me this is a bad idea, especially because I am loading MyBigModule
two times. Also because one of my controllers require the same component than the one using quickfix.
// Assembly A referencing B
public class Program
{
public static void Main(string[] args)
{
var builder = new ContainerBuilder();
buider.RegisterModule<MyBigModule>();
var container = builder.Build();
_ = HostFactory.Run(c =>
{
c.UseAutofacContainer(container);
c.Service<IMyServiceManager>(svc =>
{
svc.ConstructUsingAutofacContainer();
// ...
}
// ...
});
}
}
// Assembly B
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly())
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// ...
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
// Assembly B
public class WebHost : IWebHost
{
// ...
public void Start()
{
WebApp.Start<Startup>("someUrl");
}
}
// Assembly B
public class MyBigModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register<WebHost>.As<IWebHost>();
// ...
}
}
My first approach was to pass an Action<IAppBuilder>
to the WebHost
constructor, that is created within Main()
. Something like this:
public class Program
{
public static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterModule<MyBigModule>();
var container = builder.Build();
var webhost = new WebHost("someUrl", app =>
{
var config = new HttpConfiguration();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// ....
});
builder.RegisterInstance(webost);
// ...
}
}
However I would have to build my container first and then add another registration later. Which doesn't follow the recommendation that a container should be considered immutable. Another alternativ would be to pass the container instance down to my WebHost
s Startup
class.
It seems that I need to have a registration of my container inside the container itself. How would I do that? Maybe there is a better approach? I hope it's clear what I am struggling with.
I am pretty sure there must be a better way to wire up webapi's resolver. Any ideas and feedback is very appreciated.
I solved it in the meantime, thanks to this post. We can inject an instance of ILifetimeScope
to the constructor without having to register anything.
// Assembly A referencing B
public class Program
{
public static void Main(string[] args)
{
var builder = new ContainerBuilder();
buider.RegisterModule<MyBigModule>();
var container = builder.Build();
_ = HostFactory.Run(c =>
{
c.UseAutofacContainer(container);
c.Service<IMyServiceManager>(svc =>
{
svc.ConstructUsingAutofacContainer();
// ...
}
// ...
});
}
}
// Assembly B
public class WebHost : IWebHost
{
private readoly ILifetimeScope scope
public WebHost(ILifetimeScope scope)
{
this.scope = scope;
}
public void Start()
{
WebApp.Start("someUri", app => {
var config = new HttpConfiguration
{
DependencyResolver = new AutofacWebApiDependencyResolver(this.scope)
};
// ...
});
}
}
// Assembly B
public class MyBigModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register<WebHost>.As<IWebHost>();
// ...
}
}