Я использую структуру, которая позволяет мне перехватывать некоторые точки входа.
Рамка рамки не является веб-запросом, а не потоком, а не временным, что-то вроде потокового, но я видел много мест с повторным использованием потоков.
Поэтому мне нужна настраиваемая область, где я говорю, с чего начать и где заканчивать область.
Поскольку у меня много зависимостей, большинство из них определяются в статическом контракторе, потому что они не имеют гражданства.
У меня есть одна зависимость, которую на самом деле нужно вводить при каждом перехвате инфраструктуры.
Это метод перехвата и то, как я делаю инъекцию (я не называю этот метод, это делает каркас). Так что мне нужно здесь, чтобы внедрить AppContext
и убедиться, что Castle всегда разрешает мне правильный контекст (в пределах области)
public void Execute(AppContext context)
{
using (var s = CastleContainer.Container.BeginScope())
{
CastleContainer.Container.Register(Component.For<AppContext>().LifestyleScoped().Instance(context));
var logic = CastleContainer.Container.Resolve<ICustomerLogic>();
// begin invocation
}
}
ICustomerLogic
имеет зависимость от ICustomreDal
и ICustomreDal
имеет зависимость в AppContext
.
Поэтому, когда я разрешаю Resolve<ICustomerLogic>()
я хочу быть уверенным, что ICustomreDal
имеет текущий AppContext
.
ICustomerLogic
и зарегистрирован как singleton, а ICustomreDal зарегистрирован как переходный.
Первое исполнение работает нормально, второе исполнение я получаю:
Не удалось зарегистрировать AppContext. Уже есть компонент с этим именем. Вы хотите изменить существующий компонент? Если нет, убедитесь, что вы указали уникальное имя.
Разве замок не должен делать сегментацию области, поэтому каждая область имеет свои собственные зависимости?
Что я делаю не так?
Обратите внимание, что мы говорим о 50 казнях за секунду.
BeginScope не относится к регистрации, это касается только разрешения компонентов. Он будет следить за тем, чтобы какой-либо компонент, созданный в используемом статусе, со статусом "Сфера охвата" был освобожден (если необходимо), когда заканчиваются операторы использования. Он не отменяет регистрацию компонентов, зарегистрированных в блоке. В общем, это плохая идея зарегистрировать свои компоненты в нескольких местах. Только регистрируйте компоненты при запуске приложения.
Я много боролся с чем-то подобным и, наконец, использовал этот обходной путь, и я не был полностью доволен, но если есть кто-нибудь с лучшим решением, я бы хотел услышать. Адаптированный к вашей ситуации выглядел бы примерно так:
в вашем регистрационном коде используйте:
Component.For<ICustomerLogic>().ImplementedBy<CustomerLogic>().LifestyleScoped
Component.For<AppContext >().UsingFactoryMethod(() => (AppContext)Thread.GetNamedDataSlot("context")).LifestyleTransient() // or scoped
адаптируйте функцию Execute к:
public void Execute(AppContext context)
{
using (var s = CastleContainer.Container.BeginScope())
{
Thread.SetData(Thread.GetNamedDataSlot("context"), context);
var logic = CastleContainer.Container.Resolve<ICustomerLogic>();
Thread.SetData(Thread.GetNamedDataSlot("context"), null);
// begin invocation
}
}
Удачи,
Marwijn.