How to turn a Service Locator pattern into a real dependency injection pattern?

I asked a more general question a minute ago: How to organize the use of the DI Framework in an application? , and the feedback I received was that I used the Locator Pattern Service, not the true DI, as Martin Fowler points out here: http://martinfowler.com/articles/injection.html

Actually, I read this article only the other day, but apparently I did not quite understand it.

So let's say I have the following code:

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<ICreditCardInfo>.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 ... } 

In this example, I could add a dependency to the constructor, and I think this is the right way to fix the 'this' script.

But what if I really need to create an unknown number for the object in question (or is there any other legitimate reason why I would need to create a dependency on the fly in the class)?

+4
source share
3 answers

This example gives the impression that you are trying to create a data transfer object by naming ICreditCardInfo using an IoC container. Such objects should not have any real dependencies, such as a service. The correct way to create a DTO is to use the new operator:

 return new CreditCardInfo( MakeHex(card.EncTrack1), MakeHex(card.EncTrack2), MakeHex(card.EncMP), MakeHex(card.KSN), MakeHex(card.MPSts), ipad.Serial, "MAGENSA_V5"); 
+7
source

Embed the factory object for ICreditCardInfo in the MagTekIPAD constructor

 public class MagTekIPAD : ICardReader { private readonly Func<ICreditCardInfo> factory; public MagTekIPAD(Func<ICreditCardInfo> factory) { this.factory = factory; } public ICreditCardInfo GetCardInfo() { var info = factory(); // ... return info; } } 

Func<T> delegates can automatically generate multiple containers if they know how to instantiate T , so you don’t need to define factory interfaces or abstract factory classes.

+3
source

As Fowler noted, Service Locator is more direct and less error prone.

In some dependency attachment constructs, you need to declare whether you are dealing with Singleton , or they may have different lives .

-one
source

Source: https://habr.com/ru/post/1397553/


All Articles