Как добавить только некоторые параметры конструктора с помощью Autofac в сочетании с использованием InjectionModule - PullRequest
5 голосов
/ 31 мая 2011

Резюме:

Как объединить инъекционный модуль с обычными contain.Resolve() вызовами при регистрации?

~ Обновление (через 5 часови после обратной связи) ~:

Использование RegisterType <> в отличие от Register () не решает фактический уровень сложности, который я имею в производствекод, я обновил демонстрационный код на BitBucket, чтобы включить общий ISecond , с примерами: IMagic и CreateMagic (интерфейс, класс соответственно).

Обновлен код репо HG, а также ссылка на PasteBin ниже.

Подробности:

Существует класс с 2 зависимостями

public SomeClassWithILogDependency(ILog log, ISecond<T> second)

'ILog' имеет определенный для него InjectionModule, например, как в документации

( LogforIntegration ), см. Нижнюю часть сообщения

Если класс имеет только 1 зависимость, то эта строка регистрации Autofac работает в простейшем сценарии:

builder.RegisterType<SomeClassWithILogDependency>()
.As<IUseILog>()
.PropertiesAutowired();

НО

Мне нужно позвонить container.Resolve<ISecond<T>>() при регистрации для получения дополнительных параметров в классе, но что-то подобное не работает:

builder.Register(
    c => new SomeClassWithILogDependency(
        c.Resolve<ILog>(), c.Resolve<ISecond<T>>()))
    .As<IUseILog>()
    .PropertiesAutowired(); //with or without this

* * * * * * * * * * * * * * * * * * * * c.Resolve<ILog>() * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;Что касается того, что я пропустил, или совершенно другой стратегии?Я надеюсь, что решение не в том, чтобы больше InjectionModules ...

Полный код, размещенный на PasteBin.com в виде одного файла

или весьрешение от bitbucket.org

hg clone https://NickJosevski@bitbucket.org/NickJosevski/autofaclog4netdemo

Код модуля впрыска (чтобы завершить эту запись):

public class LogInjectionModule : Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry registry, IComponentRegistration registration)
    {
        registration.Preparing += OnComponentPreparing;
    }

    private static void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
        var t = e.Component.Activator.LimitType;

        e.Parameters = e.Parameters.Union(new[]
            {
                new ResolvedParameter(
                (p, i) => p.ParameterType == typeof (ILog),
                (p, i) => LogManager.GetLogger(t))
            });
    }
}

1 Ответ

9 голосов
/ 07 июня 2011

Благодаря предложению bentayloruk решение фактически использовалось:

WithParameter(/* ... */)

Таким образом, регистрационный код теперь выглядит следующим образом:

builder.RegisterType<SomeClassWithILogDependency<IMagic>>()
.As<IUseILog>()
.WithParameter(
    (pi, c) => pi.ParameterType == (typeof(ISecond<>)),
    (pi, c) => c.ResolveNamed<ISecond<IMagic>>("second")
    );

Образец приложения обновлен, но не запись пастбина.

Дополнительная информация:

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

pi.ParameterType == (typeof(CreateMagic))

Причиной этого является мое производство SomeClassWithILogDependency не имеет своего универсального параметра, заключенного в интерфейс, но я решил сделать пример приложения, показывающий, что проблема работает немного по-другому, но приводит к той же проблеме.

//demo:
class SomeClassWithILogDependency<TTypeOfISecond> : IUseILog
{
    public SomeClassWithILogDependency(ILog log, ISecond<TTypeOfISecond> second)
}
//-------------- vs --------------
//production:
public class RealClass<TOne, TTwo>, IRealClass<TOne, TTwo>
{
    public RealClass(ILog log, TOne t1, TTwo t2)
}
...