Unity: как указать, использовать ли конкретный экземпляр типа при разрешении другого типа - PullRequest
6 голосов
/ 06 марта 2009

Я пытаюсь сделать следующее в Unity:

У меня есть тип со следующим конструктором

public Type1(Type2 firstDependency, Type3 secondDependency)

При разрешении Type1 с использованием Unity я хочу указать конкретный экземпляр для Type2 для внедрения. Этот конкретный экземпляр Type2 не зарегистрирован в контейнере. Type3 зарегистрирован в контейнере и должен решаться как обычно.

Чтобы быть более конкретным, рассмотрим Type1 класс DocumentViewer. Type2 является конкретным Document. Type3 является SpellingChecker.

Я хочу разрешить DocumentViewer для Document, который известен только во время выполнения. Можно создать несколько DocumentViewer экземпляров для различных Documents.

Как я могу это сделать?

Ответы [ 6 ]

2 голосов
/ 06 марта 2009

Вот краткий пример, который я сделал, вы используете RegisterInstance или вы можете использовать Lifetime management Claas

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

    container.RegisterType<Type1>();

    container.RegisterInstance<Type2>(new Type2());

    Type1 t = container.Resolve<Type1>();

    Type2 t2 = container.Resolve<Type2>();

    Type3 t3 = container.Resolve<Type3>();

    Console.ReadKey();
}

public class Type1
{
}

public class Type2
{
}

public class Type3
{
    private Type1 t;
    private Type2 t2;
    public Type3(Type1 t, Type2 t2)
    {
        this.t = t;
        this.t2 = t2;
    }
}

Обновление: Я включил тип с двумя параметрами в конструктор, чтобы показать, что он также может быть разрешен.

0 голосов
/ 21 апреля 2011

Вы можете использовать иерархию контейнеров, пожалуйста, прочитайте мой ответ на аналогичный вопрос здесь: Microsoft Unity. Как указать определенный параметр в конструкторе? .

Единственная разница в том, что вы должны использовать RegisterInstance() в своем дочернем контейнере вместо RegisterType(). И, возможно, нет, это зависит от того, создавали ли вы экземпляр ранее вне вашего кода или нет.

0 голосов
/ 21 апреля 2009

Использовать фабрику.

public class Type1Factory
{
  private Type3 type3;

  public Type1Factory(Type3 _type3)
  {
     type3 = _type3;
  }

  public GetType1(Type2 type2)
  {
    return new Type1(type2, type3);
  }
}

Назовите это так:

// SpellingChecker is subclass of Type3
IUnityContainer container = new UnityContainer();
container.RegisterType<Type3>(typeof(SpellingChecker));

// DocumentViewer is subclass of Type2
Type1Factory factory = container.Resolve<Type1Factory>();
Type1 type1 = factory.GetType1(new DocumentViewer());

Это предполагает, что вы пытаетесь использовать Unity только для разрешения зависимости Type3 и что у вас нет контроля над конструкторами в Type1. Если вы можете редактировать Type1, воспользуйтесь предложением Alexader R., чтобы Unity разрешил только конструктор с одним параметром.

0 голосов
/ 06 марта 2009

Если у вас есть класс с несколькими конструкторами, вы можете решить, какой конструктор используется контейнером Unity, используя атрибут InjectionConstructor. Это дает вам возможность установить некоторые параметры вручную.


public class Test
{
    public Test()
    {
    }

    // Always use the following constructor
    [InjectionConstructor]
    public Test(Type1 type1) : this()
    {
    }

    public Test(Type1 type1, Type2 type2) : this(type1)
    {
    }
}

0 голосов
/ 06 марта 2009

Попробуйте использовать именованные экземпляры:


IUnityContainer container = new UnityContainer();
container.RegisterType<Type1>();
container.RegisterType<Type2>("Instance 1", new ContainerControlledLifetimeManager());
container.RegisterType<Type2>("Instance 2", new ContainerControlledLifetimeManager());
container.RegisterType<Type3>();

Type1 type1 = container.Resolve<Type1>();
if (type1 == ...)
{
  Type2 instance1 = container.Resolve<Type2>("Instance 1");
}
else
{
  Type2 instance2 = ontainer.Resolve<Type2>("Instance 2");
}


Вы можете выполнить некоторые проверки типа 1 и решить, какой экземпляр типа 2 вам понадобится. Обратите внимание, что параметр «новый ContainerControlledLifetimeManager ()» будет инициализировать одиночный экземпляр типа с сопротивлением, поэтому вы всегда получите один и тот же экземпляр типа 2.

Обновление: То же самое с интерфейсами. Надеюсь, это поможет.


IUnityContainer container = new UnityContainer();
container.RegisterType<TextDocument>();
container.RegisterType<ImageDocument>();
container.RegisterType(typeof (IView), typeof (TextView), "Text", new ContainerControlledLifetimeManager());
container.RegisterType(typeof (IView), typeof (ImageView), "Image", new ContainerControlledLifetimeManager());

IDocument document = container.Resolve<TextDocument>();

IView view = null;
if (document is TextDocument)
{
    view = container.Resolve<IView>("Text");
}
else
{
    view = container.Resolve<IView>("Image");
}

view.Show();

0 голосов
/ 06 марта 2009

Я не хочу регистрировать экземпляр Type2 в исходном контейнере. Экземпляр типа 2 может отличаться для разных экземпляров типа 1.

Моя следующая попытка - создать дочерний контейнер и зарегистрировать там конкретный экземпляр типа 2.

...