使用 IoC(C) 的 Factory 的簡單示例

工廠也可以與控制反轉(IoC)庫一起使用。

  • 這種工廠的典型用例是當我們想要基於執行時未知的引數(例如當前使用者)建立物件時。
  • 在這些情況下,有時很難(如果不是不可能)配置 IoC 庫來處理這種執行時上下文資訊,因此我們可以將其包裝在工廠中。

  • 假設我們有一個 User 類,其特徵(ID,安全許可級別等)在執行時是未知的(因為當前使用者可能是使用該應用程式的任何人)。
  • 我們需要獲取當前使用者併為他們獲取 ISecurityToken,然後可以使用它來檢查是否允許使用者執行某些操作。
  • ISecurityToken 的實現將根據使用者的級別而變化 - 換句話說,ISecurityToken 使用多型

在這種情況下,我們有兩個實現,它們也使用標記介面,以便更容易地將它們識別到 IoC 庫中; 在這種情況下,IoC 庫只是由抽象 IContainer 組成和識別。

另請注意,許多現代 IoC 工廠都具有本機功能或外掛,允許自動建立工廠,並且無需標記介面,如下所示; 然而,由於並非所有人都這樣做,這個例子迎合了一個簡單,最低階的功能概念。

//describes the ability to allow or deny an action based on PerformAction.SecurityLevel
public interface ISecurityToken
{
    public bool IsAllowedTo(PerformAction action);
}

//Marker interface for Basic permissions
public interface IBasicToken:ISecurityToken{};
//Marker interface for super permissions
public interface ISuperToken:ISecurityToken{};

//since IBasictoken inherits ISecurityToken, BasicToken can be treated as an ISecurityToken
public class BasicToken:IBasicToken
{
     public bool IsAllowedTo(PerformAction action)
     {
         //Basic users can only perform basic actions
         if(action.SecurityLevel!=SecurityLevel.Basic) return false;
         return true;
     }
}

public class SuperToken:ISuperToken
{
     public bool IsAllowedTo(PerformAction action)
     {
         //Super users can perform all actions         
         return true;
     }
}

接下來我們將建立一個 SecurityToken 工廠,它將作為我們的 IContainer 的依賴

public class SecurityTokenFactory
{
   readonly IContainer _container;
   public SecurityTokenFactory(IContainer container)
   {
      if(container==null) throw new ArgumentNullException("container");
   }

   public ISecurityToken GetToken(User user)
   {
      if (user==null) throw new ArgumentNullException("user);
      //depending on the user security level, we return a different type; however all types implement ISecurityToken so the factory can produce them.
      switch user.SecurityLevel
      {
          case Basic:
           return _container.GetInstance<BasicSecurityToken>();
          case SuperUser:
           return _container.GetInstance<SuperUserToken>();
      }
   }
}

一旦我們用 IContainer 註冊了這些:

IContainer.For<SecurityTokenFactory>().Use<SecurityTokenFactory>().Singleton(); //we only need a single instance per app
IContainer.For<IBasicToken>().Use<BasicToken>().PerRequest(); //we need an instance per-request
IContainer.For<ISuperToken>().Use<SuperToken>().PerRequest();//we need an instance per-request 

消費程式碼可以使用它在執行時獲取正確的令牌:

readonly SecurityTokenFactory _tokenFactory;
...
...
public void LogIn(User user)
{
    var token = _tokenFactory.GetToken(user);
    user.SetSecurityToken(token);
}

通過這種方式,我們可以從工廠提供的封裝以及 IoC 庫提供的生命週期管理中受益。