WCF 依赖注入-- Attribute
最近,工作之余学习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容器,以便于后面依赖的注入。
publicclassNInjectContainer : NinjectModule{publicoverridevoidLoad(){Bind<IUserRepository>().To<UserRepository>();Bind<UserService>().ToSelf().InSingletonScope();}privateIKernel _kernel;publicIKernel StandardKernel{get{if(_kernel ==null){_kernel =newStandardKernel(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接口,该类主要提供一种在整个服务内修改或插入自定义扩展的机制
publicclassNInjectServiceBehaviorAttribute : Attribute, IServiceBehavior{publicvoidValidate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase){}publicvoidAddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters){}publicvoidApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase){foreach(variteminserviceHostBase.ChannelDispatchers){vardispatcher = itemasChannelDispatcher;if(dispatcher !=null){dispatcher.Endpoints.ToList().ForEach(ep =>{ep.DispatchRuntime.InstanceProvider =newNInjectInstanceProvider(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号