На нашем игровом сервере одновременно может происходить несколько сражений (игр). В каждой игре космические корабли могут двигаться по прямой.
Хотелось бы, чтобы разрешение команды, которая будет двигать космический корабль по прямой во всех играх было одинаковым и выглядело как:
var cmd = Ioc.Resolve<ICommand>("Movement", obj)
где obj - это космический корабль.
Но в разных играх могут быть установлены разные правила для движения, например, в одной игре игроки договорились, что двигатели космических кораблей работают на топливе, которое расходуется во время движения, и, если оно закончилось, корабль теряет способность к движению. А в другой игре игроки посчитали, что топливо сильно усложняет игру и не стали использовать это правило.
Нам необходимо, чтобы код Ioc.Resolve<ICommand>("Movement", obj) контструировал команду движения по правилам, которые были установлены для этой игры.
Для этих целей будем использовать Scope'ы - области видимости зависимостей.
Поскольку в каждой игре будут свои правила, то нам нужно как минимум свою область видимости зависимостей для каждой игры.
Предположим, что у нас есть ссылка на нужную область видимости scope.
Тогда, перед тем как разрешить зависимость "Movement", установим текущей нужную нам область видимости.
var cmd = IoC.Resolve<ICommand>("Scopes.Current.Set", scope);
cmd.Execute();
Теперь можно разрешать зависимость в текущей области видимости:
var movement = Ioc.Resolve<ICommand>("Movement", obj);
Нет необходимости устанавливать текущую область видимости перед каждой операцией. В рамках одного потока после установки текущая область видимости поменяется только тогда, когда явно будет установлена новая.
В рамках конкретной игры рекомендуется устанавливать текущей область видимости зависимостей, соотвествующую данной игре, в начале выполнения любой последовательности команд этой игры.
У каждой области видимости зависимостей, кроме корневой, есть родительская.
Это делается для того, чтобы не пришлось копировать все зависимости, которые могут пригодиться в создаваемой области видимости, например, зависимость "IoC.Register" и т.д.
Родительский scope можно указать явно, передав как параметр при разрешении зависимостей, либо неявно - родительским будет текущий scope, а в случае, если текущий scope еще не был установлен в данном потоке, то родительским будет назначен корневой scope.
Пример: Scope без явного указания родительского.
var createdScope = Ioc.Resolve<object>("Scopes.Create");
Пример: Scope с явным указанием родительского.
var createdScope = Ioc.Resolve<object>("Scopes.Create", parentScope);
Создание новой области видимости не меняет текущую область видимости в потоке.