如何基于注入上下文自定义注入实例?

时间:2019-05-21 08:13:57

标签: c# autofac

我目前正在将应用程序从Ninject迁移到Autofac 4。在将解析的类实例注入* somewhere ^之前,我们有一种逻辑来设置它的某些属性。在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中找不到相似的内容。我已经尝试了OnActivatingOnActivated钩子,但是这些钩子似乎不提供此信息,并且与Ninject的钩子相比似乎略有不同。

1 个答案:

答案 0 :(得分:1)

实例可以在生命周期范围内共享。为了避免任何副作用, 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)));

如果要访问目标实例,也可以使用目标的ActivatingActivated事件。