Я просто смотрел курс внедрения зависимостей на PluralSight, который кое-что прояснил для меня.Но, несмотря на то, что он охватывает несколько слоев, также не было никакой информации о том, что именно вам нужно делать, когда вам нужно просто создать новые объекты в вашем коде .
.это последняя часть головоломки, которую я изо всех сил пытаюсь понять.Я знаю о Compisition Root и примерно, как его использовать.Я знаю, что нужно избегать ServiceLocator и не передавать контейнер IoC через все уровни кода, определяя его как параметр ctor практически в каждом классе в кодовой базе (что я и видел рядом в компании, в которой работалза).
Давайте рассмотрим два примера, приведенных ниже, где я считаю, что непрактично или невозможно передать все.
Я могу внедрить зависимости, но я не могу все внедрить, это не называетсяВ конце концов, инъекция объектов, поэтому проблема заключается в том, как динамически создавать объекты Doee внутри цикла:
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;
}
}
Теперь в некоторых «менее динамичных» случаях проблема заключается в том, что для некоторых классов ввода-вывода нетинтерфейс или доступный абстрактный базовый класс, что означает, что с ними сложно разобраться в тестовом коде, а также я даже не знаю, как обрабатывать их с помощью контейнера IoC, такого как класс Process:
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}");
}
}
То, что я сделал до сих пор, - это ввел в обоих случаях абстрактный класс фабрики, который я могу внедрить, и это дает мне то, что мне нужно, когда это необходимо (т.е. динамически в цикле).У меня есть реализация для производственного использования.В тестовом коде я могу либо реализовать его, либо просто смоделировать (так как он абстрактный).Для класса Process я ввел прокси-класс с интерфейсом (I) ProcessProxy, который проходит через вызовы к реальному классу Process.Я также могу легко посмеяться над этим, если мне нужно.Затем эти два примера превращаются в то, что я перечислил ниже.
Мой вопрос заключается в том, является ли правильный путь в этих двух случаях (что является моей главной заботой)?Я знаю, что я мог бы вызвать сомнительные ответы, но я просто пытаюсь выяснить, является ли это рекомендуемым способом в духе чистой и прямой текстовой книги, подобной реализации DependencyInjection и CompositionRoot.Если это не самый предпочтительный способ, то что это?
Пример цикла после рефакторинга и DI включен:
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;
}
}
Пример процесса после рефакторингаи DI включен:
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}");
}
}