如何在WCF的IDispatchMessageInspector消息检查器中注入服务?
WCF消息检查器依赖注入失败原因及实现方法
核心原因
你遇到的注入失效问题和Autofac配置本身无关,核心问题是:WCF运行时默认不会从Autofac容器中解析IDispatchMessageInspector实例。绝大多数开发者添加消息检查器时都是直接手动new实例后加入运行时管线,这个手动创建的实例完全脱离容器管控,你在容器中做的注册、属性注入配置都不会作用到WCF实际调用的检查器实例上。
另外你贴的注册代码存在拼写错误:类名写成了MessagaeValidator,正确类名是MessageValidator,这也会导致容器注册找不到对应类型。
推荐实现方式(构造函数注入,稳定性更高)
不建议使用属性注入,构造函数注入可以在编译期就检查依赖缺失,避免运行时空引用问题。
- 改造消息检查器,通过构造函数声明依赖
public class MessageValidator : IDispatchMessageInspector { private readonly IFeatureService _featureService; // 直接通过构造函数注入依赖,不需要额外加特性 public MessageValidator(IFeatureService featureService) { _featureService = featureService ?? throw new ArgumentNullException(nameof(featureService)); } public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { // 业务逻辑直接使用_featureService即可 } public void BeforeSendReply(ref Message reply, object correlationState) { // 按接口要求实现即可 } }
- 自定义服务行为,同样通过构造函数注入消息检查器实例
消息检查器需要通过服务/端点行为挂载到WCF管线,自定义行为的依赖也从容器解析,避免手动new实例:
public class MessageValidationBehavior : IServiceBehavior { private readonly MessageValidator _messageValidator; public MessageValidationBehavior(MessageValidator messageValidator) { _messageValidator = messageValidator; } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) { foreach (EndpointDispatcher endpoint in channelDispatcher.Endpoints) { // 直接使用注入好的检查器实例,不要手动new endpoint.DispatchRuntime.MessageInspectors.Add(_messageValidator); } } } }
- 注册依赖并在初始化服务宿主时从容器解析行为
首先清理掉之前拼写错误的检查器注册,换成正确的注册逻辑:
// 注册消息检查器,生命周期可根据IFeatureService的生命周期调整,不强制单例 builder.RegisterType<MessageValidator>(); // 注册自定义服务行为 builder.RegisterType<MessageValidationBehavior>(); // 其余WCF服务、IFeatureService的注册保持原有逻辑即可 var container = builder.Build();
初始化WCF服务宿主时,必须使用Autofac提供的AutofacServiceHost替代原生ServiceHost,并且从容器解析行为实例后再加入宿主配置,不要手动new行为:
// 用Autofac的服务宿主替代原生宿主 var serviceHost = new AutofacServiceHost(typeof(你的WCF服务类), new Uri("服务监听地址")); // 从容器解析行为,此时行为内部依赖的检查器、检查器依赖的IFeatureService会全部自动注入完成 var validationBehavior = container.Resolve<MessageValidationBehavior>(); serviceHost.Description.Behaviors.Add(validationBehavior); // 后续添加服务端点、开启服务的逻辑和原有代码保持一致 serviceHost.AddServiceEndpoint(typeof(你的服务契约), new BasicHttpBinding(), ""); serviceHost.Open();
如果一定要用属性注入
如果坚持用属性注入的方式,不需要在容器中注册检查器做PropertiesAutowired,只需要在手动创建检查器实例后,主动调用容器的属性注入方法即可:
var validator = new MessageValidator(); // 手动触发容器对已有实例的属性注入 container.InjectProperties(validator); // 再把注入完成的validator加入到MessageInspectors集合即可
这种方式容易因为忘记调用注入方法出现空引用,非必要不推荐。
注意:如果是通过配置文件、自定义Attribute特性的方式挂载消息检查器/行为,WCF会自动通过无参构造函数创建行为实例,完全脱离容器管控,这种方式下任何注入配置都不会生效,必须改成宿主初始化时从容器解析实例手动挂载的模式。
内容的提问来源于stack exchange,提问作者Ask
相关产品推荐
相关产品推荐

