2012-06-14 23 views
4

嗨我開始使用Simple Injector DI container爲我的所有項目,並希望如何適合一些建議是強大的功能,以我的要求。簡單的噴油器使用不同的裝飾器爲不同的命令

我有一對夫婦的命令處理程序裝飾的將包裹命令:

public class TransactionCommandHandlerDecorator<TCommand> 
    : ICommandHandler<TCommand> 
{ 
    private readonly ICommandHandler<TCommand> handlerToCall; 
    private readonly IUnitOfWork unitOfWork; 

    public TransactionCommandHandlerDecorator(
     IUnitOfWork unitOfWork, 
     ICommandHandler<TCommand> decorated) 
    { 
     this.handlerToCall = decorated; 
     this.unitOfWork = unitOfWork; 
    } 

    public void Handle(TCommand command) 
    { 
     this.handlerToCall.Handle(command); 
     unitOfWork.Save(); 
    } 
} 

互斥裝飾:

public class TransactionCommandHandlerWithMutexDecorator<TCommand> 
    : ICommandHandler<TCommand> 
{ 
    private readonly ICommandHandler<TCommand> handlerToCall; 
    private readonly IUnitOfWork unitOfWork; 
    private static object Lock = new object(); 

    public TransactionCommandHandlerWithMutexDecorator(
     IUnitOfWork unitOfWork, 
     ICommandHandler<TCommand> decorated) 
    { 
     this.handlerToCall = decorated; 
     this.unitOfWork = unitOfWork; 
    } 

    public void Handle(TCommand command) 
    { 
     lock (Lock) 
     { 
      this.handlerToCall.Handle(command); 
      unitOfWork.Save(); 
     } 
    } 
} 

在某些情況下,它纔有意義包裹在這種阻塞方式的一些命令(通過使用TransactionCommandHandlerWithMutexDecorator),並允許其他人在所有線程(使用TransactionCommandHandlerDecorator)進行無障礙訪問,此外,如果不在命令類型之間共享互斥鎖 - 使用我當前的代碼,該鎖定是靜態的並且是在所有類型之間共享。

所以到我的問題:

1)如何我可以申請TransactionCommandHandlerWithMutexDecorator到一個特定的命令或命令,並使用TransactionCommandHandlerDecorator對於其餘的 - 我會用ExpressionBuilt事件?

2)我是否需要爲每個要裝飾的命令創建一個新類(以確保每個命令有唯一的鎖對象),還是有一些方法(使用攔截)?

欣賞上述最佳方法的建議。

感謝,

克里斯

回答

8

與我當前的代碼,鎖是靜態的,將所有類型之間 共享。

這是不正確的。 Generic types don't share static members。對於每個TCommand都會有一個新的靜態類型。換句話說,Decorator<int>將具有與Decorator<string>不同的static object Lock實例。

如果你想要另一種方式,因此所有命令都有1個單一的鎖,這會有點困難。你基本上可以做三件事:

  1. 從一個非泛型基礎派生裝飾器,並在那裏定義鎖。
  2. 定義靜態非泛型類中的鎖定並從通用裝飾器中引用該類。
  3. 將鎖移至非泛型類並將其作爲正常依賴注入到裝飾器中。

但是,這不是你想要的。您想要的行爲是默認情況下發生的情況,這與簡單注射器無關。這就是泛型在C#和.NET中的工作原理。

如何申請TransactionCommandHandlerWithMutexDecorator到 特定命令或命令,並使用 TransactionCommandHandlerDecorator爲休息

這是比你想象的更容易。有一個RegisterDecorator過載需要在Predicate<T>,它允許您告訴何時裝飾。這可能是這樣的:

// Some helper methods 
private static Type GetCommandType(Type handlerType) 
{ 
    return handlerType.GetGenericArguments()[0]; 
} 

private static bool IsMutexCommand(Type commandType) 
{ 
    // Determine here is a class is a mutex command. 
    // Example: 
    return typeof(IMutexCommand).IsAssignableFrom(commandType); 
} 

// Decorator registration with predicates. 
container.RegisterDecorator(
    typeof(ICommandHandler<>), 
    typeof(TransactionCommandHandlerWithMutexDecorator<>), 
    c => IsMutexCommand(GetCommandType(c.ServiceType))); 

// Decorator registration with predicates. 
container.RegisterDecorator(
    typeof(ICommandHandler<>), 
    typeof(TransactionCommandHandlerDecorator<>), 
    c => !IsMutexCommand(GetCommandType(c.ServiceType))); 

應有盡有用簡單的噴油器RegisterDecorator被higly優化。在正常情況下*謂詞將被調用一次。

*當多個線程在同一時間同時請求同一個實例時,可能會多次調用該謂詞,但是在構建的表達式被緩存並且構建了委託之後,將不會再調用該謂詞。

+0

謝謝史蒂文我剛剛意識到閱讀你的回覆你是對的,就像我需要/想要開箱即用的具體實現一樣。 感謝迄今爲止的幫助,我將如何按照第1個問題去裝飾一些命令? – g18c

+0

@ g18c:對不起,我錯過了你最後一個問題。請參閱我的更新。 – Steven

相關問題