Autofac не поддерживает передачу параметров родительскому/потребительскому объекту, и эти параметры стекают вниз на дочерние объекты.
Как правило, я бы сказал, что требует, чтобы потребитель знал, что находится за интерфейсами его зависимостей, является плохим дизайном. Позвольте мне объяснить:
Из вашего дизайна у вас есть два интерфейса: IMasterOfPuppets
и IPuppet
. В примере у вас есть только один тип IPuppet
- NamedPuppet
. Имея в виду, что точка даже имея интерфейс, чтобы отделить интерфейс от реализации, вы можете также иметь это в вашей системе:
public class ConfigurablePuppet : IPuppet
{
private string _name;
public ConfigurablePuppet(string name)
{
this._name = ConfigurationManager.AppSettings[name];
}
}
Две вещи, чтобы отметить там.
Во-первых, у вас есть другую реализацию IPuppet
, который должен работать на месте любого другого IPuppet
при использовании с IMasterOfPuppets
потребителем. Реализация IMasterOfPuppets
никогда не должна знать, что реализация IPuppet
изменилась ... и вещь, потребляющая IMasterOfPuppets
, должна быть еще удалена.
Во-вторых, как пример NamedPuppet
и новый ConfigurablePuppet
принимать строковый параметр с тем же именем, но это означает что-то другое для реализации основы. Поэтому, если ваш потребительский код делает то, что вы показываете в примере, - передавая параметр, который должен быть , имя - то у вас, вероятно, есть проблема с дизайном интерфейса. См.: Liskov substitution principle.
точки существо, учитывая, что IMasterOfPuppets
реализация нуждается в IPuppet
прошла в, это не должно волновать, как IPuppet
был построен, чтобы начать с, или то, что на самом деле поддержав IPuppet
. Как только он знает, вы нарушаете разделение интерфейса и реализации, а это значит, что вы можете также уйти с интерфейсом и просто пройти в NamedPuppet
объектах все время.
Что касается параметров прохождения, Autofac имеет поддержку параметров.
Рекомендованный и наиболее распространенный тип передачи параметров является during registration, потому что в это время вы можете настроить все на уровне контейнера и вы не используете сервисный центр (который generally considered an anti-pattern).
Если вам нужно сдать параметры во время разрешения Autofac also supports that. Однако при прохождении во время разрешения, это больше сервис-локатор-иш и не так уж велико, потому что, опять же, это означает, что потребитель знает, что он потребляет.
Вы можете сделать некоторые причудливые вещи с помощью lambda expression registrations, если вы хотите подключить параметр, поступающий от известного источника, например конфигурации.
builder.Register(c => {
var name = ConfigurationManager.AppSettings["name"];
return new NamedPuppet(name);
}).As<IPuppet>();
Вы можете также сделать некоторые модные вещи, используя the Func<T>
implicit relationship в потребителе:
public class MasterOfPuppets : IMasterOfPuppets
{
IPuppet _puppet;
public MasterOfPuppets(Func<string, IPuppet> puppetFactory)
{
_puppet = puppetFactory("name");
}
}
Делать это является эквивалентом использования TypedParameter
типа string
при разрешении. Но, как вы можете видеть, это исходит от прямого потребителя IPuppet
, а не что-то, что стекает сквозь стек всех разрешений.
Наконец, вы также можете использовать Autofac modules, чтобы сделать некоторые интересные сквозные вещи так, как вы видите в log4net integration module example. Используя подобный метод, вы можете вставить конкретный параметр во всем мире по всем разрешениям, но он не обязательно обеспечивает возможность передачи параметра во время выполнения - вам нужно будет поместить источник параметра внутри модуля.
Точка Autofac поддерживает параметры, но не то, что вы пытаетесь сделать. Я бы настоятельно рекомендовал перепроектировать то, как вы делаете, поэтому у вас фактически нет необходимости делать то, что вы делаете, или чтобы вы могли обратиться к нему одним из вышеупомянутых способов.
Надеюсь, это должно заставить вас двигаться в правильном направлении.
Я не совсем согласен с конструктивным следствием этого. Пример, который я дал, был простым, может быть, слишком простым. Но в реальном решении имеет смысл передать определенный контекст/состояние и просачиваться во все зависимости, требующие его. В любом случае, я проверил документацию для Unity, и эта функция фактически поддерживается в форме ["ParameterOverrides"] (http://msdn.microsoft.com/en-us/library/ff660920 (v = pandp.20) .aspx) Итак, вопрос в том, есть ли аналогичная функция в Autofac или другом контейнере ioc (рядом с Unity, который является довольно тяжелым). – JoefGoldstein
Funcs/factories в Autofac фактически позволяют передавать данные при разрешении экземпляров. Я думаю, что это было бы правильное решение проблемы OP. –
Извинения за короткий первоначальный ответ - я был на своем телефоне в выходные и хотел попробовать разблокировать OP. Я расширил ответ и уточнил. –