How to apply dependency injection to an abstract factory

I just finished Mark Seemann's book “Dependency Injection” in .NET, and now I'm trying to refactor some old code. (At this stage, I do not rely on any specific DI container, but simply try to move all the dependencies to one place).

I consider the following factory class, which defines ArchiveTypeby reading the first few bytes of the archive with archiveReader.GetArchiveType(), and then returns an instance ArchiveRestorerbased on the enumeration ArchiveType.

public class ArchiveRestorerFactory : IArchiveRestorerFactory
{
    public ArchiveRestorer Create(ArchiveReader archiveReader)
    {
        ArchiveType type = archiveReader.GetArchiveType();
        switch (type)
        {
            case ArchiveType.CurrentData:
                return new CurrentDataArchiveRestorer(archiveReader);
                break;
            case ArchiveType.HistoricalData:
                return new HistoricalDataArchiveRestorer(archiveReader);
                break;
            case ArchiveType.AuditTrail:
                return new AuditTrailArchiveRestorer(archiveReader);
                break;
            default:
                throw new Exception("ArchiveRestorerFactory error: Unknown value for ArchiveType.");
        }
    }
}

How can I reorganize it so that the class does not depend on specific types CurrentDataArchiveRestorer, HistoricalDataArchiveRestorerand AuditTrailArchiveRestorer?

Should I move three specific restorers to the factory constructor?

public ArchiveRestorer Create(ArchiveReader archiveReader, 
    ArchiveRestorer currentDataArchiveRestorer, 
    ArchiveRestorer historicalDataArchiveRestorer, 
    ArchiveRestorer auditTrailDataArchiveRestorer)
{
    // guard clauses...
    // assign to readonly fields
}

, , ? , 20 ?

, factory , new .

?

+5
5

, , , factory , Create().

factory.

.

:

case ArchiveType.CurrentData:
                return _currentDateArchiveRestorerFactory.Create(archiveReader);
                break;

, , factory, . , enum, switch.

_restorerFactory.Create(ArchiveType.CurrentData);
+2

ArchiveReader ArchiveRestorer? :

public class ArchiveRestorerFactory : IArchiveRestorerFactory
{
    public ArchiveRestorer Create(ArchiveReader archiveReader)
    {
        ArchiveRestorer restorer = archiveReader.GetArchiveRestorer();
        return restorer;
    }
}

, factory , , ArchiveReader.

+2

, create , , . , .

+1
source
interface ILogger
{
    void Log(string data);
}

class Logger : ILogger
{
    .
    .
    .
}

At this point, you are using the intermediate factory object to return the registrar that will be used inside the component:

class MyComponent
{
  void DoSomeWork()
  {
    // Get an instance of the logger
    ILogger logger = Helpers.GetLogger();
    // Get data to log
    string data = GetData();

    // Log
    logger.Log(data);
  }
}

class Helpers
{
  public static ILogger GetLogger()
  {
    // Here, use any sophisticated logic you like
    // to determine the right logger to instantiate.

    ILogger logger = null;
    if (UseDatabaseLogger)
    {
        logger = new DatabaseLogger();
    }
    else
    {
        logger = new FileLogger();
    }
    return logger;
  }
}
class FileLogger : ILogger
{
    .
    .
    .
}

class DatabaseLogger : ILogger
{
    .
    .
    .
}
0
source

I would solve this problem by agreeing to a naming convention and using the Unity ability to register registrations. An example of this is here: https://dannyvanderkraan.wordpress.com/2015/06/29/real-world-example-of-dependency-injection-based-on-run-time-values/

0
source

All Articles