I was just watching a Dependency Injection course on PluralSight that cleared up a couple of things for me. But despite the fact that it goes over a few layers, there was also no info about what exactly is the way to go when you just have to new up objects in your codde.
This is the last piece of the puzzle that I'm struggling to grasp. I know about Compisition Root and roughly how to use it. I know to avoid ServiceLocator and to avoid passing down the IoC container through all levels of the code by defining it as a ctor parameter in just about every class in the code base (which I both have seen side by side in a company that I worked for).
Let's consider the two examples below where I believe it is unpractical to impossible to hand in everything.
I can inject dependencies, but I can't possibly inject everything, it isn't called Object Injection after all, so the problem is how to dynamically create Doee objects inside of a loop:
public class MyClass
{
private IVerifyer _verifyer;
public MyClass(IVerifyer verifyer)
{
_verifyer = verifyer;
}
public IList<Doer> PrepareDoingSomething(IList<IDoees> doees)
{
var doers = new List<Doer>();
foreach (var doee in doees)
{
if (!Verifyer.Verify(doee)) throw new Exception("Blablabla...");
doers.Add(new Doer(doee));
}
return doers;
}
}
Now in some "less dynamic" cases, the problem is that for some IO classes there is neither an interface nor an abstract base class available, which means that they are difficult deal with in test code, and also I wouldn't even know how to handle them with an IoC container, like the Process class:
public class Processor
{
public Process ProcessSomething(IProcessee processee)
{
// do some pre-processing stuff here
// static Start() returns a new Process instance
return Process.Start("C:\MyApp.exe", $"-option {processee.Option1}");
}
}
What I've done so far is to introduce in both cases an abstract factory class that I can inject and that gives me what I need when need it (i.e. dynamically in a loop). I have an implementation for production use. In test code I can either implement it or just mock it (since it's abstract). For the Process class I've introduced a proxy class with interface (I)ProcessProxy that passes through the calls to the actual Process class. I can also easily mock that if I need to. The two examples then turn into what I've listed below.
My question is, is that the right way to go in these two cases (which are my main concerns)? I know that I might trigger opinionated answers, but I'm just trying to figure out if that is the recommended way in the spirit of a clean and straight forward text book-like DependencyInjection and CompositionRoot implementation. If that's not the preferred way to go, then what is it?
Loop example after refactoring and DI enabled:
public class MyClass
{
private IVerifyer _verifyer;
private AbstractDoerFactory _doerFactory;
public MyClass(IVerifyer verifyer, AbstractDoerFactory doerFactory)
{
_verifyer = verifyer;
_doerFactory = doerFactory;
}
public IList<Doer> PrepareDoingSomething(IList<IDoees> doees)
{
var doers = new List<Doer>();
foreach (var doee in doees)
{
if (!_verifyer.Verify(doee)) throw new Exception("Blablabla...");
doers.Add(_doerFactory.GetNewDoer(doee));
}
return doers;
}
}
Process example after refactoring and DI enabled:
public interface IProcessProxy : IDisposable
{
TextReader StandardOutput { get; }
TextReader StandardError { get; }
int ExitCode { get; }
Start(string fileName, string arguments);
void Kill();
}
public class Processor
{
private AbstractProcessProxyFactory _processProxyFactory;
public Processor(AbstractProcessProxyFactory processProxyFactory)
{
_processProxyFactory = processProxyFactory;
}
public IProcessProxy ProcessSomething(IProcessee processee)
{
// do some pre-processing stuff here
var processProxy = _processProxyFactory.GetProxyFactory();
return processProxy.Start("C:\MyApp.exe", $"-option {processee.Option1}");
}
}