Итак, у меня есть:
Применение A: Требуется класс B (различная сборка)
Класс B: Требуется класс C (опять же, другая сборка)
Класс C: использует контейнер для разрешения различных объектов, но временем жизни контейнера (и объектов, которые он разрешает) должен управлять корень композиции.
Мне кажется, я понимаю, как это будет работать в большинстве случаев, но в классе C мне нужно разрешить на основе свойства объекта, который передается.
Я думаю, что я спрашиваю, стал ли контейнер зависимостью и, как таковой, как лучше получить его там, где это необходимо (не уверен, что я действительно хотел бы передать его через кучу Конструкторы - будет ли путь внедрения свойства?)
Я считаю, что этот источник настолько прост и понятен, насколько я могу:
namespace InjectionTest
{
using System;
using Microsoft.Practices.Unity;
public class ApplicationA
{
static void Main(string[] args)
{
using (IUnityContainer container = new UnityContainer())
{
// Normally I'd use this, but for clarity in the example, I'm doing it in code.
//container.LoadConfiguration();
container.RegisterType<IClassB, ClassB>();
container.RegisterType<IClassC, ClassC>();
container.RegisterType<IFooBuilder, FrobBuilder>("frob");
container.RegisterType<IFooBuilder, WidgetBuilder>("widget");
IClassB machine = container.Resolve<IClassB>();
InitialObject bar = new InitialObject() { Name = "widget" };
machine.doSomethingWithBar(bar);
bar = new InitialObject() { Name = "frob" };
machine.doSomethingWithBar(bar);
}
}
}
public class ClassB : IClassB
{
IClassC classC { get; private set; }
public ClassB(IClassC classc)
{
this.classC = classc;
}
public void doSomethingWithBar(InitialObject bar)
{
var foo = this.classC.BuildMyFoo(bar);
/*
* Do something else with foo & bar
* */
}
}
public interface IClassB
{
void doSomethingWithBar(InitialObject bar);
}
public class ClassC : IClassC
{
public ResultObject BuildMyFoo(InitialObject bar)
{
IFooBuilder builder = null;
//How best do I get my container here?
//IFooBuilder builder = container.Resolve<IFooBuilder>(bar.Name);
return builder.build(bar);
}
}
public interface IClassC
{
ResultObject BuildMyFoo(InitialObject bar);
}
public class InitialObject
{
public string Name { get; set; }
}
public class ResultObject
{
public string SomeOtherData { get; set; }
}
public interface IFooBuilder
{
ResultObject build(InitialObject bar);
}
public class FrobBuilder : IFooBuilder
{
public ResultObject build(InitialObject bar)
{
throw new NotImplementedException();
}
}
public class WidgetBuilder : IFooBuilder
{
public ResultObject build(InitialObject bar)
{
throw new NotImplementedException();
}
}
}
Редактировать: Вот как я заставил это работать с внедрением свойства:
Я изменил ClassC:
public class ClassC : IClassC
{
[Dependency]
public IUnityContainer Container { get; set; }
public ResultObject BuildMyFoo(InitialObject bar)
{
IFooBuilder builder = null;
//How best do I get my container here?
builder = Container.Resolve<IFooBuilder>(bar.Name);
return builder.build(bar);
}
}
и обновил мой метод Main в ApplicationA:
public void Main()
{
using (IUnityContainer container = new UnityContainer())
{
// Normally I'd use this, but for clarity in the example, I'm doing it in code.
//container.LoadConfiguration();
container.RegisterType<IClassB, ClassB>();
container.RegisterType<IClassC, ClassC>();
container.RegisterType<IFooBuilder, FrobBuilder>("frob");
container.RegisterType<IFooBuilder, WidgetBuilder>("widget");
using (IUnityContainer child = container.CreateChildContainer())
{
container.RegisterInstance<IUnityContainer>(child);
IClassB machine = container.Resolve<IClassB>();
InitialObject bar = new InitialObject() { Name = "widget" };
machine.doSomethingWithBar(bar);
bar = new InitialObject() { Name = "frob" };
machine.doSomethingWithBar(bar);
}
}
}