TL; DR.У меня круговая зависимость, и я не знаю, как ее сломать.
Main.csproj: имеет Program.cs, который вручную создает DiService
var diService = new DiService(new Container());
diService.Register();
Метод register ищет в CurrentDomain сборки и регистрирует коллекциигде для данного интерфейса существует несколько реализаций, или же они регистрируют конкреции 1-1.
Затем он использует контейнер для создания абстрактной фабрики.
var diFactory = diService.Registry.GetInstance<IDiFactory>();
Вот фабрика
public class DiFactory : IDiFactory
{
private readonly Container registry;
public DiFactory(Container registry)
{
this.registry = registry;
}
public T Get<T>()
{
var reqT = typeof(T);
return (T) registry.GetInstance(reqT);
}
}
Зависимости проекта в решении выглядят следующим образом:
Main -> A -> B,E
B -> C,D,E
C -> D,E
D -> E
DiService и DiFactory живут в проекте B с другими службами.Не то чтобы это имело значение.Я думаю, у меня возникла бы та же проблема, если бы они были в Main.
Все объекты в проектах B-E имеют конструктор, внедренный в DiFactory, чтобы они могли решать, какие объекты им нужны во время выполнения.Но для того, чтобы C мог использовать его, он должен зависеть от B, который является циклической зависимостью.
Если я переместу материал DI в новый проект F, то все проекты могут зависеть от этого, но какЗаводская ссылка на типы в других проектах без создания другой циклической зависимости?
Я следовал документации для IRequestHandler, я просто не делал словарь.Скорее всего, у меня есть недостаток дизайна, но я не вижу, что это такое.
Вот пример взаимодействия между объектами для LinqPad - не компилируется, но выглядит правильно.
void Main()
{
var diService = new Mine.Services.MyDiService();
var diFactory = diService.Container.GetInstance<Mine.Services.IMyFactory>();
var rand = new Random();
var next = rand.Next(1, 100);
var task = next % 2 == 0
? diFactory.Get<Mine.Tasks.EvenTask>()
: (Mine.Tasks.IMyTask)diFactory.Get<Mine.Tasks.OddTask>();
task.Perform();
}
namespace Mine.Common
{
public class MyCommonObject { }
}
namespace Mine.Services
{
public class FakeContainer
{
public T GetInstance<T>() { return default(T); }
}
public interface IMyOtherService { void DoSomethingElse(); }
public class MyOtherService : IMyOtherService
{
public void DoSomethingElse()
{
throw new NotImplementedException();
}
}
public class MyService
{
private readonly IMyFactory myFactory;
public MyService(IMyFactory myFactory)
{
this.myFactory = myFactory;
}
public void MyServiceMethod()
{
var thing = myFactory.Get<Mine.Common.MyCommonObject>();
}
}
public interface IMyFactory { T Get<T>(); }
public class MyDiService
{
public FakeContainer Container;
}
public class MyFactory : IMyFactory
{
private FakeContainer Container;
public MyFactory(FakeContainer container)
{
// obviously this is really a SImple Injector Container
Container = container;
}
public T Get<T>()
{
return default(T);
}
}
}
namespace Mine.Kernel {
public interface IMyMultiConcrete { void Do(); }
public class MyConcreteBase : IMyMultiConcrete
{
protected readonly Mine.Services.IMyFactory MyFactory;
public MyConcreteBase(Mine.Services.IMyFactory myFactory)
{
MyFactory = myFactory;
}
public void Do()
{
MyFactory.Get<Mine.Common.MyCommonObject>();
}
}
public class MyConcrete1 : MyConcreteBase
{
public MyConcrete1(Mine.Services.IMyFactory myFactory) : base(myFactory) {}
public void Do()
{
MyFactory.Get<Mine.Common.MyCommonObject>();
}
}
}
namespace Mine.Tasks
{
public interface IMyTask { void Perform(); }
public class TaskBase : IMyTask
{
protected readonly Mine.Services.IMyOtherService MyOtherService;
public TaskBase(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
{
MyOtherService = myOtherService;
}
public void Perform()
{
MyOtherService.DoSomethingElse();
}
}
public class OddTask : TaskBase
{
public OddTask(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
: base(myFactory, myOtherService) { }
}
public class EvenTask : TaskBase
{
public EvenTask(Mine.Services.IMyFactory myFactory, Mine.Services.IMyOtherService myOtherService)
: base(myFactory, myOtherService) { }
}
}