使用 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 庫提供的生命週期管理中受益。