DEBUG
, так и в режиме RELEASE
Иногда мне нужно прочитать данные из самого запроса, чтобы инициализировать сервис, от которого зависит некий 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
в вашем загрузчике.
Вау, это действительно сработало, большое спасибо :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());
}
Самый полезный комментарий
Не знаю насчет стандарта, но я думаю, что этого можно добиться, прописав контекст или запрос в контейнере запроса. Просто переопределите
ConfigureRequestContainer
в вашем загрузчике.