在Simple Injector中無法取消註冊。你可以replace an existing registration,但是這個方法在處理裝飾器時不起作用。裝飾者通過在ExpressionBuilt
事件中添加一個代表添加到Simple Injector內部。由於註冊代理無處存儲,目前在技術上不可能「註銷」裝飾註冊。
解決方法是簡單地而不是註冊裝飾器。這聽起來可能很愚蠢,但這是我一直在使用的一種做法,即使是使用其他容器。
你能做些什麼,例如,將註冊的公共部分提取到一個單獨的方法,我們稱之爲BuildUp
。此方法缺少與使用它的不同應用程序不同的註冊。在你的情況下,你至少有2個「應用程序」;真正的應用程序和集成測試項目。這兩個項目都可以撥打BuildUp
,並在致電BuildUp
之前或之後添加額外的註冊。例如:
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(InnerMostCommandHandlerDecorator<>));
CompositionRoot.BuildUp(container);
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(OuterMostCommandHandlerDecorator<>));
這種方法似乎在你的情況很好地工作,因爲你要添加一個「最外面的」裝飾。此外,讓BuildUp
在您的註冊中留下「漏洞」,通常會很容易看到某些應用程序忘記填寫空白時的情況,因爲您可以通過調用container.Verify()
來讓Simple Injector快速失敗。
另一種常用的方式將配置對象傳遞給BuildUp
方法。該配置對象可以包含必要的信息,以便根據調用者的要求進行正確的註冊。舉例來說,這樣的配置對象可以有一個簡單的布爾標誌:
public static void Build(Container container, ApplicationConfig config) {
// Lot's of registrations
if (config.AddGlobalExceptionHandler) {
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(GlobalExceptionHandlerCommandHandlerDecorator<>));
}
}
的配置對象傳遞到BuildUp
方法也是解耦從配置系統BuildUp
方法的好方法。這使您可以在集成測試期間更輕鬆地撥打BuildUp
,而不必在測試項目中擁有完整配置文件的副本。
除了使用標誌屬性外,還可以在配置對象中包含裝飾器的完整列表,並讓BuildUp
方法遍歷它並註冊它們。這使得他們在註冊前呼叫者從列表中刪除或添加裝飾:
var config = new ApplicationConfig();
// Remove decorator
config.CommandHandlerDecorators.Remove(
typeof(AuthorizationCommandHandlerDecorator<>));
// Add decorator after another decorator
config.CommandHandlerDecorators.Insert(
index: 1 + config.CommandHandlerDecorators.IndexOf(
typeof(TransactionCommandHandlerDecorator<>)),
item: typeof(DeadlockRetryCommandHandlerDecorator<>));
// Add an outer most decorator
config.CommandHandlerDecorators.Add(
typeof(TestPerformanceProfilingCommandHandlerDecorator<>));
CompositionRoot.BuildUp(container, config);
public static void BuildUp(Container container, ApplicationConfig config) {
// Lot's of registrations here.
config.CommandHandlerDecorators.ForEach(type =>
container.RegisterDecorator(typeof(ICommandHandler<>), type));
}
我已經在過去使用所有這三種方法非常成功。選擇哪個選項取決於您的需求。