Autofac - разрешение компонента с параметрами динамически - PullRequest
5 голосов
/ 04 августа 2010

У меня есть класс, который принимает интерфейс в качестве аргумента конструктора. Существует две реализации этого интерфейса, и я хочу решить, какую реализацию использовать во время выполнения, основываясь на переменной.

Проблема в том, что приведенный выше класс глубоко в иерархии объектов, которая разрешена Autofac, и поэтому я не могу передать аргумент.

Я пытаюсь достичь чего-то похожего ниже.

public interface IInterface1 {}
public interface IInterface2 {}

public class Class1 : IInterface2
{
    public Class1(IInterface1 interface1)
    {
    }
}

public class Class2
{
    public Class2(IInterface2 interface2)
    {
    }
}

public class Class3
{
    public void GetClass2Instance(string interface1ImplementationToChoose)
    {
        // want to change which implementation of IInterface1 is resolved based on the interface1ImplementationToChoose variable
        var class2 = container.Resolve<Class2>();
    }
}

Есть идеи?

UPDATE:

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

Есть ли способ заставить другую реализацию IInterface1 быть переданной в Class1, если Class2 ничего не знает об этом?

Спасибо

1 Ответ

6 голосов
/ 05 августа 2010

Да, введите фабрику, которая скрывает, как выбираются типы:

public class Class3
{
   private Func<string, Class2> _class2Factory;
   public Class3(Func<string, Class2> class2Factory)
   {
        _class2Factory = class2Factory;
   }

   public void GetClass2Instance(string interface1ImplementationToChoose)
   {
       var class2 = _class2Factory(interface1ImplementationToChoose);
   }
}

А затем настройку контейнера, что-то вроде этого:

builder.RegisterType<Implementation1>().Named("imp1").As<IInterface1>();
builder.RegisterType<Implementation2>().Named("imp2").As<IInterface1>();
builder.Register<Func<string, Class2>>(c => 
    {
        var context = c.Resolve<IComponentContext>();
        return imp => new Class2(context.Resolve<IInterface1>(imp));
    });
builder.RegisterType<Class3>();

Теперь вы можете использовать Class3 вот так:

public class Class4
{
     public Class4(Class3 class3)
     {
         var class2with1 = class3.GetClass2Instance("imp1");
         var class2with2 = class3.GetClass2Instance("imp2");
     }
}

ПРИМЕЧАНИЕ: Я предположил, что вы имели в виду, что Class2 следует вводить с различными реализациями одного и того же интерфейса IInterface1.Ваш пример немного сбивает с толку, так как вы показываете два класса, которые реализуют разные интерфейсы.

...