Проблемы с установкой контейнера Lamar IoC - PullRequest
0 голосов
/ 11 декабря 2018

Я пытался заставить Ламара работать на нашу инъекцию зависимости, но мой недостаток опыта заставил меня испытать некоторое горе.

У меня есть простой фиктивный контроллер:

[Route("[controller]")]
public class TestController : Controller
{
    [HttpGet]
    public int GetRandom()
    {
        TestService service = new TestService();
        int value = service.GetRandomNumber();


        return value;
    }
}

Внутри TestService находится репозиторий интерфейса, куда я хотел бы применить DI.

Я добавил UseLamar в мой Program.cs, и мой startup.cs выглядит так:

    public void ConfigureContainer(ServiceRegistry services)
    {
        services.AddMvc();
        services.Scan(s =>
        {
            s.Assembly("Test.Components");
            s.WithDefaultConventions();
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Invalid");
        });

        app.UseMvc();
    }

Из прочтения документации я считаю, что Lamar должен автоматически сопоставить мой интерфейс с моим типом, поскольку они имеют одинаковое имя (IRepository -> Repository), хотя это не то, что я вижу.

Я уверен, что что-то пропустил, но я перебрал документацию и пытался поискать реальные примеры безрезультатно.Есть ли строки, которые мне не хватает в Startup.cs?Нужен ли моему Сервису конструктор для установки репозитория?

1 Ответ

0 голосов
/ 12 декабря 2018

Вообще говоря, вы хотите внедрить свои зависимости через конструктор.В некоторых случаях вы могли бы использовать другой подход, но в моем опыте более 90% случаев можно использовать инжекцию конструктора.

Так что, действительно, вы захотите добавить IRepository в ваш конструктор TestService.Однако из вашего кода похоже, что вам не хватает чего-то более фундаментального в том, как работает внедрение зависимостей.

TestService service = new TestService();

Когда вы используете new для создания объекта, you контролируют жизненный цикл и объем этого объекта.Смысл использования инфраструктуры внедрения зависимостей - позволить it (каркас / контейнер) управлять зависимостями и их областью действия / жизненным циклом для вас.Если вы создаете экземпляр объекта с помощью контейнера внедрения зависимостей, он разрешает для вас зависимости этого объекта - он также управляет зависимостями этих зависимостей, и так далее, так что вы можете иметь цепочкузависимостей, которые разрешаются без проработки сложностей инициализации большого графа объектов вручную (используя «new»).

Чтобы решить ваш непосредственный вопрос, вы можете сделать что-то вроде (это плохой код - не рекомендуется!):

TestService service = container.Resolve<ITestService>();

Контейнер будет контейнером lamar, в котором вы регистрируете свои типы - я не знаком с lamar, поэтому синтаксис Resolve () может выглядеть немного иначе.Это разрешило бы TestService и добавило бы репозиторий и все аргументы конструктора класса TestService.

Предпочтительный способ сделать это - разрешить цепочку зависимостей на границе (точке входа) вашего приложения, которая являетсясам твой контроллер.Таким образом, ваш контроллер должен принять ITestService в качестве аргумента конструктора, а контейнер / инфраструктура разрешит TestController => TestService => Repository.

Для того, чтобы это работало, вам нужно выполнить небольшую разводку.Как я уже сказал, я не знаю lamar, поэтому я не уверен, как заставить это работать с Asp.net Core.

В Asp.Net Framework WebAPI это выглядело бы примерно так с помощью Unityдля DI:

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new UnityControllerActivator(container));

Этот код запускается при запуске приложения и сообщает платформе ASP.Net: когда приходит запрос, разрешите соответствующий контроллер и все его зависимости, используя предоставленный контейнер.

...