Нужно ли мне регистрировать контейнер autofa c с самим собой, чтобы подключить преобразователь зависимостей webapi? - PullRequest
0 голосов
/ 28 мая 2020

Я пишу службу Windows с использованием Topshelf, которая должна запускать собственный проект webapi и службу FIX на основе quickfix / n. Пожалуйста, обратите внимание на сокращенный код ниже, который пока работает.

Однако есть одна проблема - теперь в моем приложении есть два экземпляра контейнера. Мое чутье подсказывает мне, что это плохая идея, особенно потому, что я загружаю MyBigModule два раза. Также потому, что один из моих контроллеров требует того же компонента, что и тот, который использует 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>();

        // ...
    }
}

Мой первый подход заключался в передаче Action<IAppBuilder> конструктору WebHost, который создается внутри Main(). Примерно так:

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

        // ... 
    }
}

Однако мне пришлось бы сначала построить свой контейнер, а потом добавить еще одну регистрацию. Это не соответствует рекомендации о том, что контейнер следует считать неизменяемым. Другой альтернативой было бы передать экземпляр контейнера моему классу WebHost s Startup.

Кажется, мне нужна регистрация моего контейнера внутри самого контейнера. Как мне это сделать? Может есть подход получше? Надеюсь, понятно, с чем я борюсь.

Я почти уверен, что должен быть лучший способ подключить резолвер webapi. Мы очень ценим любые идеи и отзывы.

1 Ответ

0 голосов
/ 28 мая 2020

Я решил это тем временем, благодаря этой публикации . Мы можем вставить экземпляр ILifetimeScope в конструктор, не регистрируя ничего.

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

        // ...
    }
}
...