Регистрация каскадных зависимостей (дубль 2) - PullRequest
1 голос
/ 23 февраля 2012

Вчера я попытался задать этот вопрос, но не смог понять его смысл.Итак, я построил репродукцию, чтобы продемонстрировать свою проблему.

В следующей программе я решаю, что в Бар должен быть введен Foo и Дурак.Дурак также вводит Foo в него.Суть в том, что я хочу, чтобы Бар и Дурак использовали один и тот же Foo.В следующем коде этого не происходит.

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();

        Console.WriteLine("Resolving Bar");
        container.Resolve<Bar>();
        Console.ReadLine();
    }
}

public class Foo
{
    public Foo()
    {
        Console.WriteLine("Foo created " + this.GetHashCode());
    }
}

public class Fool
{
    public Foo Foo { get; set; }
    public Fool(Foo foo)
    {
        Foo = foo;
        Console.WriteLine("Fool created with injected Foo " + foo.GetHashCode());
    }
}
public class Bar
{
    public Bar(Foo foo, Fool fool)
    {
        Console.WriteLine("Bar created with injected Foo " + foo.GetHashCode());
        Console.WriteLine("Bar created with injected Fool.Foo " + fool.Foo.GetHashCode());
        // I want foo == fool.Foo
    }
}
public class Blat
{
    public Blat(Foo foo, Fool fool)
    {
        Console.WriteLine("Blat created with injected Foo " + foo.GetHashCode());
        Console.WriteLine("Blat created with injected Fool.Foo " + fool.Foo.GetHashCode());
    }
}

Я мог бы разрешить типы и определить конкретный конструктор инъекций в методе Main, но у меня возникли сложности.В этом случае я также создаю Blat и Bar.Уловка в том, что я хочу, чтобы Blat и Bar использовали разные Foo.

Рассмотрим:

   static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();
        var foo = container.Resolve<Foo>();
        container.RegisterType<Fool>(new InjectionConstructor(foo));
        var fool = container.Resolve<Fool>();
        container.RegisterType<Bar>(new InjectionConstructor(foo, fool));
        container.RegisterType<Blat>(new InjectionConstructor(foo, fool));

        Console.WriteLine("Resolving Bar");
        container.Resolve<Bar>();
        container.Resolve<Blat>();
        Console.ReadLine();
    }
}

В этом случае Bar.Foo == Bar.Fool.Foo но Blat.Foo == Bar.Foo.Другими словами, я хочу Bar.Foo == Bar.Fool.Foo && Blat.Foo! = Bar.Foo

Есть ли способ сделать это?Я буду разрешать многие типы баров и блатов, поэтому я хотел бы избежать создания дочерних контейнеров для каждого баров, блатов и т. Д.в реальном мире у меня есть что-то вроде следующего:

 BaseViewModel(Context context, ServiceA a, ServiceB b)

Каждый элемент управления должен быть создан ViewModel, который использует другой контекст.В каждой viewModel сервисы должны использовать один и тот же контекст.Поэтому я хочу, чтобы Unity создавала контексты a и b, используя один и тот же контекст.

Я мог бы сделать что-то похожее на то, что вы предлагаете.Я мог бы установить свойство Context для служб в конструкторе BaseViewModel, но это мне кажется странным.Сейчас я просто обновляю сервисы в конструкторе, но я бы предпочел сделать это с Unity, чтобы они не были так тесно связаны.Я надеялся, что есть более элегантный способ.

Ответы [ 2 ]

2 голосов
/ 24 февраля 2012

С вашим IUnityContainer, зарегистрируйте Foo с PerResolveLifetimeManager, то есть:

static void Main(string[] args)
{
    IUnityContainer container = new UnityContainer();
    container.RegisterType<Foo>(new PerResolveLifetimeManager());

    Console.WriteLine("Resolving Bar");
    container.Resolve<Bar>();
    container.Resolve<Blat>();
    Console.ReadLine();
}

Когда вы разрешите Bar, тот же экземпляр Foo будет введен в Bar и вводится в Fool.

Затем, когда вы разрешите Blat, новый экземпляр Foo будет введен в Blat и в Fool.

То есть Bar.Foo == Bar.Fool.Foo и Blat.Foo == Blat.Fool.Foo но Bar.Foo != Blat.Foo и Bar.Fool.Foo != Blat.Fool.Foo.

Каждый раз, когда вы вызываете container.Resolve, для этого графа разрешается только один экземпляр Foo, это то, что делает PerResolveLifetimeManager.

0 голосов
/ 23 февраля 2012

Задумывались ли вы когда-нибудь так:

public class Bar
{
  public Bar(Fool fool)
  {
    this.Fool = fool;
  }
  public Foo Foo
  { 
    get { return this.Fool.Foo; }
    set { this.Fool.Foo = value; }
  }
  public Fool Fool { get; set; }
}

, где Bar.Foo - это просто установщик / получатель удобства для Bar.Fool.Foo?Зачем вводить один и тот же экземпляр дважды?

...