WCF 依赖注入-- Attribute
2013-06-27 17:39 yangtam 阅读(932) 评论(0) 收藏 举报最近,工作之余学习WCF(Windows Communication Fundation)时,感觉自己还有好多的东西需要学习呀⊙﹏⊙b汗,于是想记录下自己学习WCF的心得,以鼓励自己再接再厉,同时希望可以为其他想学习WCF的园友们抛砖引玉,虽然有很多大侠们已经写了很多类似的文章了。
结合现实开发项目的情形,想在WCF服务中实现构造函数的依赖注入,就像在MVC中有一个名为DefaultControllerFactory的入口一样,那么在WCF中是否也有类似的类呢?下面是在MSDN中提到了三种方法:
- 以编程方式,先将自定义服务行为添加到 Behaviors 属性,然后对 System.ServiceModel.ServiceHost 对象调用 ICommunicationObject.Open 方法。
- 创建一个可实现 IServiceBehavior 的自定义属性,并利用它来标记要修改的服务类。 构造 ServiceHost 对象时, 会使用反射来发现服务类型的属性。 如果有属性实现 IServiceBehavior,则它们将会被添加到 ServiceDescription 上的行为集合中。
- 扩展 System.ServiceModel.Configuration.BehaviorExtensionElement 类,以支持应用程序配置文件或计算机配置文件中的行为规范。
本文主要是使用第二种方法(Attribute)实现依赖注入。
在上列子之前,需要我们了解两个接口:IInstanceProvider 和 IServiceBehavior。
IInstanceProvider接口 声明一些方法,以便为服务提供服务对象,或回收该服务的服务对象。(MSDN)
IServiceBehavior接口 提供一种在整个服务内修改或插入自定义扩展的机制,包括 ServiceHostBase。(MSDN)
本例中使用的是NInject注入工具,需要了解NInject的园友可以登录官网:http://www.ninject.org/。闲话少说了,进入正题……
- 新建一个类NInjectContainer, 主要是作为IoC容器,以便于后面依赖的注入。
public class NInjectContainer : NinjectModule { public override void Load() { Bind<IUserRepository>().To<UserRepository>(); Bind<UserService>().ToSelf().InSingletonScope(); } private IKernel _kernel; public IKernel StandardKernel { get { if(_kernel == null) { _kernel = new StandardKernel(this); } return _kernel; } } }NinjectModule是Ninject提供的,想了解的可以去官网看看。
- 新建一个类NInjectInstanceProvider,该类继承 IInstanceProvider,该类主要是为服务提供服务对象,或回收该服务的服务对象
public class NInjectInstanceProvider : IInstanceProvider { public NInjectContainer Container { get; private set; } public Type ServiceType { get; set; } public NInjectInstanceProvider(Type type) { ServiceType = type; Container = new NInjectContainer(); } public object GetInstance(InstanceContext instanceContext) { return GetInstance(instanceContext, null); } public object GetInstance(InstanceContext instanceContext, Message message) { return Container.StandardKernel.Get(ServiceType); } public void ReleaseInstance(InstanceContext instanceContext, object instance) { Debug.WriteLine("ReleaseInstance"); } }
- 新建一个类NInjectServiceBehaviorAttribute,该类继承Attribute类,同时实现IServiceBehavior接口,该类主要提供一种在整个服务内修改或插入自定义扩展的机制
public class NInjectServiceBehaviorAttribute : Attribute, IServiceBehavior { 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 (var item in serviceHostBase.ChannelDispatchers) { var dispatcher = item as ChannelDispatcher; if (dispatcher != null) { dispatcher.Endpoints.ToList().ForEach(ep => { ep.DispatchRuntime.InstanceProvider = new NInjectInstanceProvider( serviceDescription.ServiceType); }); } } } } - 新建一个服务IUserService及UserService,同时将NInjectServiceBehaviorAttribute应用在需要注入的服务上面
[ServiceContract(Namespace = "http://www.iyasoft.cn.Samples")]
public interface IUserService
{
[OperationContract]
string Add(User user);
[OperationContract]
string Update(User user);
[OperationContract]
string Delete(string name);
[OperationContract]
string GetUsers();
}
[NInjectServiceBehavior]
public class UserService : IUserService
{
private readonly IUserRepository _repository;
public UserService(IUserRepository repository)
{
_repository = repository;
}
public string Add(User user)
{
return _repository.Add(user);
}
public string Update(User user)
{
return _repository.Update(user);
}
public string Delete(string name)
{
return _repository.Delete(name);
}
public string GetUsers()
{
return _repository.GetUsers();
}
}
主函数的调用如下:
class Program
{
static void Main(string[] args)
{
try
{
ServiceHostBase host = new ServiceHost(typeof(UserService));
host.Opened += (sender, e) => Console.WriteLine("server is opened");
host.Open();
var channelFactory = new ChannelFactory<IUserService>("client");
IUserService userService1 = channelFactory.CreateChannel();
Console.WriteLine(userService1.Add(new User()));
Console.WriteLine(userService1.Delete("user"));
Console.WriteLine(userService1.Update(new User()));
Console.WriteLine(userService1.GetUsers());
channelFactory.Close();
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
Console.WriteLine("\n+++ press any key to close a ServiceHost +++\n");
Console.ReadLine();
host.Close();
}
catch { }
}
这样就完成了WCF中服务的依赖注入......,下面我们看看运行结果:

我也是新学习WCF的菜鸟,不对的地方请各位大侠指出,谢谢!
浙公网安备 33010602011771号