0

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 WebHosts 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.

Matthias Güntert
  • 4,013
  • 6
  • 41
  • 89

1 Answers1

0

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

        // ...
    }
}
Matthias Güntert
  • 4,013
  • 6
  • 41
  • 89