Простая область применения инжектора для конкретного LifeStyle

1

Есть ли способ определить рамки для определенного образа жизни? Я пытаюсь реализовать свою собственную область видимости, которую я хочу сохранить в приложении, но внутренне я также создаю другую область, а затем запрос GetInstance возвращает экземпляр с внутренним областью.

Я подумал, могу ли я определить свой образ жизни как:

public class MyScopedLifestyle : ExecutionContextScopeLifestyle
{
    public MyScopedLifestyle(bool disposeInstanceWhenScopeEnds)
        : base("MyScopedLifestyle", disposeInstanceWhenScopeEnds)
    {
    }

    protected override int Length
    {
        get
        {
            return 100;
        }
    }
}

И мое использование:

var container = new Container();
container.Register<IRequestData, RequestData>(new MyScopedLifestyle());

// i had hoped I could say
//   container.BeginExecutionContextScope(MyScopedLifestyle)
// or something similar
// this is controlled by me
using (var scope1 = container.BeginExecutionContextScope())
{
    // do some stuff
    container.GetInstance<IRequestData>().RequestMarket = "en-US";

    // this is done via the webapi execution scope (using simpleinjector dependency resolver)
    using (var scope2 = container.BeginExecutionContextScope())
    {
        Assert.Equal("en-US", container.GetInstance<IRequestData>().RequestMarket); // false
    }
}

Но я не уверен, как использовать свой стиль жизни при создании внутренней области выполнения.

Я действительно хочу, чтобы мой экземпляр IRequestData, используемый в scope1, является тем же самым экземпляром IRequestData внутри области2. Можно ли достичь этого с помощью SimpleInjector?

Редактировать Я удалил тот факт, что я пытаюсь создать экземпляр объекта по запросу OWIN, а не по запросу WebAPI. В идеале я пытаюсь создать:

container.RegisterOwinRequest<IRequestData, RequestData>();

Поэтому, когда я разрешаю IFoo любом месте моего конвейера (будь то промежуточное ПО OWIN или в части WebAPI, тот же экземпляр возвращается для конкретного запроса).

Edit 2 Сменил наш IFoo/Foo/MyProperty для лучшего имени.

  • 0
    Оооо .... ты хочешь, чтобы у Foo был единый образ жизни, или я неправильно понял твой вопрос? Вы можете зарегистрировать его как Lifestyle.Singleton . Сохранять экземпляры в приложениях обычно не нужно, особенно в случае сервисов.
  • 0
    Нет простите. Я попытался сделать вопрос проще, но в процессе я думаю, что убрал эту часть. Я использую объект типа запроса, но в рамках понятия «OwinRequest». По сути, у меня есть промежуточное программное обеспечение, которое я хочу установить для каждого объекта запроса, а затем использовать его в разделе webapi моего кода. В идеале то, что я пытался создать, какова способность к container.RegisterPerOwinRequest<TInterface, TConcrete>()
Показать ещё 4 комментария
Теги:
dependency-injection
simple-injector
ioc-container

1 ответ

2

То, что вы пытаетесь выполнить с помощью привычного образа жизни, абсолютно возможно, но может быть и не так просто, потому что вам нужно будет хранить эту область где-то (возможно, в CallContext) и нужно создать метод BeginMyCustomScope который создает новую область и имеют пользовательскую реализацию Scope которая удаляет себя из CallContext когда CallContext Dispose. Я думаю, что это слишком много работы и слишком много сложностей.

Проблема возникает из-за того, что за время, когда вы хотите установить свойство RequestMarket, не существует области запроса веб-API. Способ принудительного запуска такой области - вызвать метод GetDependencyScope в HttpRequestMessage:

message.GetDependencyScope();

Сразу после этого вы можете разрешить IRequestData и он работает как ожидалось:

container.GetInstance<IRequestData>().RequestMarket = "en-US";

Однако я не уверен, доступен ли HttpRequestMessage в этот момент времени, поэтому, если нет, я думаю, что работать с DelegatingHandler как вы выразили в комментариях, является хорошей альтернативой.

Раньше хорошим способом передачи данных по стоп-косту были использование переменных, зависящих от потока, но это явно не удается при использовании моделей async/await, как в Web API и OWIN. Таким образом, новый способ сделать это - использовать CallContext. Поэтому вместо использования DelegatingHandler вы можете сделать что-то вроде этого:

container.RegisterInitializer<IRequestData>(data =>
    data.RequestMarket = (string)CallContext.LogicalGetData("RequestMarketKey"));

И когда начнется запрос OWIN, вы выполните следующее:

CallContext.LogicalSetData("RequestMarketKey", "en-US");
  • 0
    Спасибо, Стивен. Сейчас я буду придерживаться подхода DelegatingHandler , так как я не хочу брать зависимость от CallContext (только пока). Что касается объема работы, необходимого для реализации пользовательского стиля жизни, то это похоже на общий запрос ( RegisterOwinRequest , особенно при продвижении к OWIN), поэтому мне интересно, стоит ли открывать вопрос для голосования на сайте SimpleInjector, и посмотреть куда это идет.
  • 0
    @ Трис: не стесняйтесь открыть запрос на сайте проекта.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню