C# 如何根据注入上下文定制注入实例?

C# 如何根据注入上下文定制注入实例?,c#,autofac,C#,Autofac,我目前正在将应用程序从Ninject迁移到Autofac 4。我们有一个逻辑来设置已解析类实例的一些属性,然后再将其注入*somewhere^。在Ninject中,我们就是这样做的 // Ninject setup example this.Bind<IServiceContext>() .To<DefaultServiceContext>() .InCallScope() .OnActivation((ctx, instance) =>

我目前正在将应用程序从
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;
        }
    });
//Ninject安装示例
this.Bind()
.至()
.InCallScope()
.OnActivation((ctx,实例)=>
{
if(instance.Module==null){
instance.Module=ctx.Request.Target.Member.DeclaringType.FullName;
}
});
代码中的关键是使用
ctx.Request.Target.Member
我们可以访问正在进行的注入发生的构造函数信息(当然是在构造函数注入的情况下)。因此,我们可以通过将其
Module
属性设置为注入目标类型名称来初始化注入的服务类


我在
Autofac
中找不到类似的内容。我已经尝试了
OnActivating
OnActivated
钩子,但它们似乎没有提供这些信息,而且与
Ninject
的钩子相比,它们的意思似乎略有不同。

实例可以在整个生命周期范围内共享。为了避免任何副作用,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;
                    })
            });
    }
}
公共类TargetPreparingCallbackModule:模块
{
公共TargetPreparingCallbackModule(Func targetPreparing)
{
这个。_targetPreparing=targetPreparing;
}
专用只读函数_targetPreparing;
受保护的覆盖无效AttachToComponentRegistration(IComponentRegistry componentRegistry,
iComponent(组件注册)
{
registration.Preparing+=this.registration\u Preparing;
}
私有无效注册\u准备(对象发送方,准备事件参数e)
{
var t=e.Component.Activator.LimitType;
e、 参数=e.Parameters.Union(
新[]
{
新解析参数(
(p,c)=>p.ParameterType==typeof(T),
(p,c)=>{
参数=此参数。_targetPreparing(t);
T实例=c.Resolve(参数);
返回实例;
})
});
}
}
然后您可以这样使用它:

builder.RegisterModule(
    new TargetPreparingCallbackModule<Foo>(targetType => new NamedParameter("module", targetType.FullName)));
builder.RegisterModule(
新的TargetPreparingCallbackModule(targetType=>new-NamedParameter(“module”,targetType.FullName));

如果要访问目标实例,还可以使用目标的
激活
激活
事件

谢谢,我想这背后一定有一些设计决定。我将尝试一下这种方法。