Зарегистрируйте строковое значение для конкретного имени параметра

Я использую Autofac, и у меня есть несколько классов, которые запрашивают параметр типа string и name lang. Есть ли способ зарегистрировать строковое значение для всех параметров с именем «lang», чтобы оно разрешалось автоматически? Я не хочу редактировать какие-либо конструкторы, так как это не мой код (я знаю, что принятие, например, CultureInfo облегчит регистрацию..)

Что-то приводит к короткому синтаксису вроде builder.Register(lang => "en-US").As().Named("lang")

было бы идеально.

Спасибо.


person Tomas Grosup    schedule 23.04.2012    source источник


Ответы (2)


Довольно простой способ решить эту проблему — использовать специальный модуль Autofac.

Во-первых, реализуйте модуль и обработайте событие IComponentRegistration.Preparing. Здесь вы также будете хранить значение для вашего параметра:

using System;
using Autofac;
using Autofac.Core;

public class LangModule : Module:
{
  private string _lang;
  public LangModule(string lang)
  {
    this._lang = lang;
  }

  protected override void AttachToComponentRegistration(
    IComponentRegistry componentRegistry,
    IComponentRegistration registration)
  {
    // Any time a component is resolved, it goes through Preparing
    registration.Preparing += InjectLangParameter;
  }

  protected void InjectLangParameter(object sender, PreparingEventArgs e)
  {
    // Add your named parameter to the list of available parameters.
    e.Parameters = e.Parameters.Union(
      new[] { new NamedParameter("lang", this._lang) });
  }
}

Теперь, когда у вас есть собственный модуль, вы можете зарегистрировать его вместе с другими зависимостями и указать значение, которое хотите внедрить.

var builder = new ContainerBuilder();
builder.RegisterModule(new LangModule("my-language"));
builder.RegisterType<LangConsumer>();
...
var container = builder.Build();

Теперь, когда вы разрешаете любой тип со строковым параметром «lang», ваш модуль будет вставлять предоставленное вами значение.

Если вам нужно быть более конкретным, вы можете использовать PreparingEventArgs в обработчике событий, чтобы определить, например, какой тип разрешается (e.Component.Activator.LimitType) и т. д. Затем вы можете решить на лету, следует ли включать ваш параметр.

person Travis Illig    schedule 24.04.2012
comment
Еще не пробовал, но выглядит именно так, как я хотел. Большое спасибо. - person Tomas Grosup; 25.04.2012
comment
@Travis - можно ли это адаптировать для работы с внедрением свойств? - person Matthew King; 07.02.2013
comment
Я уверен, что возможно, но я оставлю это в качестве упражнения для читателя. - person Travis Illig; 07.02.2013

Взгляните на этот пример:

builder.Register<ClassName>((c, p) =>
{
var p2 = p.Named<string>("lang");
return new ClassName(p2);
});
var container = builder.Build();
var m = container.Resolve<ClassName>(new NamedParameter("lang", "en-US"));
var m2 = container.Resolve<ClassName>(new NamedParameter("lang", "fr-FR"));

вы можете разрешить свой класс и передать параметры в конструкторе.

person Anton Sizikov    schedule 23.04.2012
comment
Это работает, однако нужно автоматически выполнить это разрешение для каждого из классов, что совпадает с текущим сценарием, только с другим синтаксисом. - person Tomas Grosup; 23.04.2012
comment
Я ищу что-то, что автоматически разрешало бы этот параметр для всех классов (или всех классов данной сборки) - person Tomas Grosup; 23.04.2012
comment
Ну, когда вы вызываете Register, вы можете передать в него фабричный метод. Вы можете передать туда что-то вроде () => { return new ClassName(GetLangString()); } - person Anton Sizikov; 23.04.2012
comment
Но по-прежнему требуется вызывать это для всех классов со строковым языком в конструкторе. Я ищу решение O (1) LinesOfCode, а не O (количество задействованных классов) LOC. - person Tomas Grosup; 23.04.2012
comment
У вас есть много классов с параметрами lang в конструкторах? Хорошо, я вижу, что мой вариант не подходит. - person Anton Sizikov; 24.04.2012
comment
Я проверил модульные тесты Builder и думаю, что вы не можете сделать это с Autofac. UnitTest - person Anton Sizikov; 24.04.2012