Как настроить внедренный экземпляр на основе контекста внедрения? - PullRequest
2 голосов
/ 21 мая 2019

В настоящее время я работаю над переносом приложения из Ninject в Autofac 4.У нас была логика для установки некоторых свойств разрешенного экземпляра класса, прежде чем он будет внедрен в * где-то ^.В Ninject мы сделали это следующим образом.

// Ninject setup example
this.Bind<IServiceContext>()
    .To<DefaultServiceContext>()
    .InCallScope()
    .OnActivation((ctx, instance) =>
    {
        if (instance.Module == null) {
            instance.Module = ctx.Request.Target.Member.DeclaringType.FullName;
        }
    });

Ключ в коде заключается в том, что, используя ctx.Request.Target.Member, мы можем получить доступ к информации конструктора (в случае внедрения конструктора, конечно), где происходит текущее внедрение.,Таким образом, мы могли бы инициализировать наш внедренный класс обслуживания, установив для его свойства Module имя типа цели внедрения.

Я не могу найти ничего подобного в Autofac.Я пробовал оба крючка OnActivating и OnActivated, но, похоже, они не предоставляют эту информацию и, по-видимому, означают немного другую вещь по сравнению с крючками Ninject.

1 Ответ

1 голос
/ 21 мая 2019

Экземпляр может быть общим для всей жизни. Чтобы избежать каких-либо побочных эффектов, Autofac не сообщает нам, какой компонент запросил активированный компонент.

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

Этот модуль даст вам доступ к целевому типу при запросе T.

public class TargetPreparingCallbackModule<T> : Module
{

    public TargetPreparingCallbackModule(Func<Type, Parameter> targetPreparing)
    {
        this._targetPreparing = targetPreparing;
    }

    private readonly Func<Type, Parameter> _targetPreparing;

    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry,
            IComponentRegistration registration)
    {
        registration.Preparing += this.Registration_Preparing;
    }

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

        e.Parameters = e.Parameters.Union(
            new[]
            {
                new ResolvedParameter(
                    (p, c) => p.ParameterType == typeof (T),
                    (p, c) => {
                        Parameter parameter =  this._targetPreparing(t);
                        T instance = c.Resolve<T>(parameter);
                        return instance;
                    })
            });
    }
}

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

builder.RegisterModule(
    new TargetPreparingCallbackModule<Foo>(targetType => new NamedParameter("module", targetType.FullName)));

Вы также можете использовать событие Activating или Activated цели, если хотите иметь доступ к целевому экземпляру.

...