Nancy: Как внедрить зависимость в NancyModule, которая сама зависит от запроса?

Созданный на 25 февр. 2018  ·  4Комментарии  ·  Источник: NancyFx/Nancy

Предпосылки

  • [x] Я написал описательное название проблемы
  • [x] Я убедился, что использую последнюю версию Nancy
  • [x] Я проверил, существует ли проблема как в режиме DEBUG , так и в режиме RELEASE
  • [x] Я искал открытые и закрытые проблемы, чтобы убедиться, что о них еще не сообщалось

Описание

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

public interface IApiKeyProvider 
{
     string GetApiKey();
}

public class Service : IService
{
    private readonly IApiKeyProvider apiKeyProvider; 
    public Service(IApiKeyProvider apiKeyProvider) 
    {
           this.apiKeyProvider = apiKeyProvider;
    }

    // ... implementation
}

Я бы зарегистрировал оба так:

container.Register<IService, Service>();
container.Register<IApiKeyProvider, FromRequestApiKeyProvider>(); 

где класс FromRequestApiKeyProvider предоставляет ключ API, считывая данные из запроса. Вот что мне нужно уметь:

// Hypothetical class
public class FromRequestApiKeyProvider : IApiKeyProvider
{
    private readonly NancyRequest request;
    public FromRequestApiKeyProvider(NancyRequest request)
    {
         this.request = request;
    }

    public string GetApiKey() 
    {
         return this.request.Query["apiKey"];
    }
}

Неспособность сделать это вынуждает меня инициализировать конкретную реализацию Service внутри обработчиков запросов, что, в свою очередь, запрещает мне модульное тестирование моего NancyModule.

Другой сценарий, в котором это всплыло, - это когда я помещал данные в Items NancyContext в конвейере Before (в Bootstrapper -> ApplicationStartup), а затем мне нужно было прочитать данные Я вставил NancyContext, чтобы инициализировать какую-то службу, подобную приведенной выше.

В качестве примера для последнего сценария см. библиотеку Nancy.Serilog , где вам нужно получить контекстный регистратор из обработчика запросов, т.е. var logger = this.CreateLogger(); , где в идеале это должно быть внедрено как зависимость от NancyModule на уровне конструктора. .

Самый полезный комментарий

Не знаю насчет стандарта, но я думаю, что этого можно добиться, прописав контекст или запрос в контейнере запроса. Просто переопределите ConfigureRequestContainer в вашем загрузчике.

Все 4 Комментарий

Разве вы не можете просто зарегистрировать контекст или запрос в контейнере запросов?

Подождите, есть стандартный способ сделать это 😅, пожалуйста, где я могу найти примеры?

Не знаю насчет стандарта, но я думаю, что этого можно добиться, прописав контекст или запрос в контейнере запроса. Просто переопределите ConfigureRequestContainer в вашем загрузчике.

Вау, это действительно сработало, большое спасибо :heart: :pray: Я использовал этот код:

protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
{
    Func<ILogger> getLogger = () =>
    {
        if(!context.Items.ContainsKey("RequestId"))
        {
            return Log.Logger;
        }

        var requestId = (string)context.Items["RequestId"];
        var contextualLogger = Log.ForContext("RequestId", requestId);
        return contextualLogger;
    };

    container.Register((tinyIoc, namedParams) => getLogger());
}
Была ли эта страница полезной?
0 / 5 - 0 рейтинги