惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
F
Fortinet All Blogs
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
G
Google Developers Blog
P
Proofpoint News Feed
Recent Announcements
Recent Announcements
MyScale Blog
MyScale Blog
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
月光博客
月光博客
爱范儿
爱范儿
罗磊的独立博客
腾讯CDC
Hugging Face - Blog
Hugging Face - Blog
博客园 - 叶小钗
Vercel News
Vercel News
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog
C
Check Point Blog
美团技术团队
宝玉的分享
宝玉的分享
Microsoft Security Blog
Microsoft Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

博客园 - 大西瓜3721

基于 .NET 的 FluentValidation 验证教程 C#.NET 仓储模式详解 SVN分支/合并原理及最佳实践 Web.Config中Runtime节点-DLL版本冲突问题 工作问题 Vue资料 WCF 依赖注入-- Attribute MVC视图分析 C#简单枚举和标志枚举的用法和区别 XDate Admin.NET框架资料 日志管理之log4net+Autofac 关于NopCommerce3.6版用户登录详解 AutoFac注册的动态实例 Named和Keyed NOP源码分析 六 NOP源码分析五---set的存储 NOP源码分析四 Nop源码分析三 NOP源码分析 二 NOP源码分析 一 NopCommerce的资料 IServiceCollection和IServiceProvider 控制反转——Autofac框架 精选10款C#/.NET开发必备类库 11个免费开源后台管理系统模板 H5连接蓝牙打印机打印小票 自定义控件 - 流式布局:TagFlowLayout MVC开源CMS nginx的安装&一个最简单的配置(windows和Centos) DNS解析
轻松实现WCF服务的构造函数依赖注入
大西瓜3721 · 2026-05-26 · via 博客园 - 大西瓜3721

今天在开发博客园博客程序的WCF服务时,想在“WCF服务实现”中通过构造函数进行依赖注入。代码如下:

复制代码

    public class BlogService : IBlogService
{
private IBlogSiteService _blogSiteService;

public BlogService(IBlogSiteService blogSiteService)
{
_blogSiteService = blogSiteService;
}
}

复制代码

依赖注入容器用的是Unity,IBlogSiteService的实现已经在WCF Host运行时通过Bootstrapper进行注入,参见寂寞如此美丽:脱离Application_Start,让初始化代码更优美

可是在客户端调用这个WCF服务时,却出现异常:

The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor.
To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.

出现这个异常属正常现象,我没有告诉WCF Host,它怎么知道我要进行依赖注入,我们之间又没有心灵感应。WCF按常规办事,通过默认构造函数创建WCF服务的实例,所以引发异常。

那如何解决这个问题呢?

小软(微软)早就考虑到这一点了,提供了IInstanceProvider与IServiceBehavior接口。我们只需要实现这两个接口,并让实现IServiceBehavior的类成为一个Attribute(继承自Attribute),然后加在WCF服务实现类上,就可以实现WCF的构造函数依赖注入。

具体实现步骤如下:

一、实现IInstanceProvider接口 - IocInstanceProvider

1. 新建一个类IocInstanceProvider,实现IInstanceProvider接口。

2. 实现IInstanceProvider接口的三个方法,并引入你自己的IoC容器(比如我们用的是CNBlogs.Infrastructure.CrossCutting.IoC),也就是让WCF通过你的IoC容器获取WCF服务的实例。示例代码如下:

复制代码

public class IocInstanceProvider : IInstanceProvider
{
Type _serviceType;
IContainer _container;

public IocInstanceProvider(Type serviceType)
{
_serviceType = serviceType;
_container = CNBlogs.Infrastructure.CrossCutting.IoC.
IoCFactory.Instance.CurrentContainter;
}

#region IInstanceProvider Members

public object GetInstance(InstanceContext instanceContext, Message message)
{
return _container.Resolve(_serviceType);
}

public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}

public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
if (instance is IDisposable)
((IDisposable)instance).Dispose();
}

#endregion
}

复制代码

注:你的IoC容器要事先注入了相应的WCF服务的实例。比如我们的注入:

container.RegisterType<IBlogService, BlogService>();

其中IBlogService是WCF服务接口,BlogService是WCF服务实现。

二、实现IServiceBehavior接口 - IocServiceBehavior

1. 新建一个类IocServiceBehavior,继承自Attribute,实现IServiceBehavior

public class IocServiceBehavior : Attribute, IServiceBehavior

2. 实现IServiceBehavior的AddBindingParameters()方法,并引入之前创建的IocInstanceProvider

复制代码

public class IocServiceBehavior : Attribute, IServiceBehavior
{
#region IServiceBehavior Members

public void AddBindingParameters(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{
foreach (var item in serviceHostBase.ChannelDispatchers)
{
var dispatcher = item as ChannelDispatcher;
if (dispatcher != null)
{
dispatcher.Endpoints.ToList().ForEach(endpoint =>
{
endpoint.DispatchRuntime.InstanceProvider = new
IocInstanceProvider(serviceDescription.ServiceType);
});
}
}
}

public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
}

public void Validate(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
}

#endregion
}

复制代码

三、在WCF服务实现类上增加[IocServiceBehavior]属性

代码如下:

复制代码

[IocServiceBehavior]
public class BlogService : IBlogService
{
private IBlogSiteService _blogSiteService;

public BlogService(IBlogSiteService blogSiteService)
{
_blogSiteService = blogSiteService;
}

#region IBlogService Members

public BlogSiteDto GetBlogSiteWithPosts(int blogId,
bool withPostBody, int itemcount)
{
return _blogSiteService.GetWithPosts(blogId,
withPostBody, itemcount);
}

#endregion
}

复制代码

搞定!是不是很轻松!

上面的实现代码参考自Domain Oriented N-Layered .NET 4.0 Sample App(http://microsoftnlayerapp.codeplex.com/),如果你对DDD感兴趣,推荐阅读这个项目的代码。

代码改进

根据Artech的建议,并参考WCF Extensibility – IInstanceProvider,改进一下IocServiceBehavior的代码,实现ApplyDispatchBehavior接口,代码如下:

复制代码

public class IocServiceBehavior : Attribute, IServiceBehavior
{
#region IServiceBehavior Members

public void AddBindingParameters(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{
}

public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
if (!ed.IsSystemEndpoint)
{
ed.DispatchRuntime.InstanceProvider =
new IocInstanceProvider(serviceDescription.ServiceType);
}
}
}
}

public void Validate(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
}

#endregion
}

复制代码

小结

你IoC了吗?如果没有,你真的Out了。不仅ASP.NET可以轻松IoC(想爱容易,相处难:当ASP.NET MVC爱上IoC),而且单元测试也可以IoC(梦想成现实:用xUnit.net在单元测试中实现构造函数依赖注入)。