如何将此服务定位器模式转换为真正的dependency injection模式?
我在一分钟前问了一个更普遍的问题: 如何在应用程序中组织DI Framework使用? 我得到的反馈是,我使用的是Service Locator Pattern而不是真正的DI,正如Martin Fowler在这里指出的那样: http : //martinfowler.com/articles/injection.html
实际上,我前几天读了那篇文章,但显然还没有完全掌握它。
所以我要说我有以下代码:
interface ICardReader { string GetInfo(); void SetDebugMode(bool value); void Initialize(string accountToken); void ShowAmount(string amount); void Close(); ICreditCardInfo GetCardInfo(); } public class MagTekIPAD: ICardReader { public ICreditCardInfo GetCardInfo() { var card = GetCardDataFromDevice(); // apparently the following line is wrong? var ccInfo = Inject.New(); ccInfo.Track1 = MakeHex(card.EncTrack1); ccInfo.Track2 = MakeHex(card.EncTrack2); ccInfo.MagSignature = MakeHex(card.EncMP); ccInfo.MagSwipeKeySN = MakeHex(card.KSN); ccInfo.MagSignatureStatus = MakeHex(card.MPSts); ccInfo.MagDeviceSN = ipad.Serial; ccInfo.MSREncryptType = "MAGENSA_V5"; return ccInfo; } // Other implementation details here ... }
在这个例子中,我可以将dependency injection构造函数 – 我认为这是修复’this’场景的正确方法。
但是如果我真的需要创建一个未知数量的对象(或者是否还有其他正当理由我需要在课堂上动态创建依赖项)呢?
此示例给我的印象是,您尝试使用IoC容器以ICreditCardInfo
方式创建数据传输对象ICreditCardInfo。 这些对象不应该像服务那样具有任何真正的依赖关系。 创建DTO的正确方法是使用new
运算符:
return new CreditCardInfo( MakeHex(card.EncTrack1), MakeHex(card.EncTrack2), MakeHex(card.EncMP), MakeHex(card.KSN), MakeHex(card.MPSts), ipad.Serial, "MAGENSA_V5");
将ICreditCardInfo
对象的工厂注入到ICreditCardInfo
的构造函数中
public class MagTekIPAD : ICardReader { private readonly Func factory; public MagTekIPAD(Func factory) { this.factory = factory; } public ICreditCardInfo GetCardInfo() { var info = factory(); // ... return info; } }
如果几个容器知道如何创建T
实例,那么它们可以自动生成Func
委托,因此您不必定义工厂接口或抽象工厂类。
正如Fowler指出的那样,Service Locator是更直接的方法,并且不易出错。
一些dependency injection框架要求您声明您是在处理Singleton还是它们可以具有不同的生命周期 。