我目前正在将应用程序从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
中找不到相似的内容。我已经尝试了OnActivating
和OnActivated
钩子,但是这些钩子似乎不提供此信息,并且与Ninject
的钩子相比似乎略有不同。
答案 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)));
如果要访问目标实例,也可以使用目标的Activating
或Activated
事件。