WCF利用企业库Unity框架的IOC层次解耦
由于工作几个月来框架开发已经好久没写博客了,今天想抽点时间出来冒泡。在领域驱动开发中SOA已经成为我们开发的主流技术,在面对当前众多的UI框架选择(asp.net mvc,silverlight,wpf,winform,wp7等一些列甚至跨语言),我们能够重用和抽象的业务逻辑是不会变化的,为了屏蔽这些UI的复杂性和差异性,我们可能会采用诸如wcf soap的服务发布。再说在领域驱动开发中我们肯定会把各个逻辑分层次隔离解除耦合,这就出现了N层架构,在于我们的每一层次之间的耦合度当前流程的解决方案IOC框架,以及业务解耦AOP。这里要解决的是SOA框架WCF和IOC框架的结合。
WCF框架是一个极易扩展的框架,提供了非常多的扩展点(InstanceProvider,MessageInspector,CallContextInitializer,MessageFilter,MessageFormatter,ParameterInspector等等)。在这里IOC是作为一个容器组装创建的框架,我们需要的是对服务对象的创建,所以我们选择的当然是InstanceProvider扩展点。
多说一句废话,正如前篇利用Attribute简化Unity框架IOC注入和 AOP之PostSharp7-解决IOC 不能直接new问题,简化IOC开发和IOC对象LazyLoad中所说,我是一个固执的人,个人希望注入支持自定义配置文件,不喜欢把配置信息全部写在一个web.config/app.config中,也不喜欢el的写在同一个外部配置文件中,倾向于每个模块在一个不同的配置文件,并在模块中在区分container容器,所以特别写了每个单独配置文件的延时加载,缓存。
下面就是对InstanceProvider的扩展:
ViewCode publicclassELUnityInstanceProvider:IInstanceProvider { privateTypecontractType; privatestringcontainer; privatestringconfigFile; privatestringname; privatestaticobjectlockObj=newobject(); privatestaticDictionary<string,UnityConfigurationSection>sectionDict=newDictionary<string,UnityConfigurationSection>(); publicELUnityInstanceProvider(TypecontractType,stringcontainer,stringconfigFile,stringname) { this.name=name; this.configFile=configFile; this.contractType=contractType; this.container=container; } #regionIInstanceProvider成员 publicobjectGetInstance(System.ServiceModel.InstanceContextinstanceContext,System.ServiceModel.Channels.Messagemessage) { Microsoft.Practices.Unity.Configuration.UnityConfigurationSectionunitySection=GetUnityConfigurationSection(); if(unitySection!=null) { varcontainer=newMicrosoft.Practices.Unity.UnityContainer().LoadConfiguration(unitySection,string.IsNullOrEmpty(this.container)?unitySection.Containers.Default.Name:this.container); varobj=string.IsNullOrEmpty(this.name)?container.Resolve(this.contractType):container.Resolve(this.contractType,this.name); varpiabAtttr=obj.GetType().GetCustomAttributes(typeof(ELPolicyinjectionAttribute),false)asELPolicyinjectionAttribute[]; if(piabAtttr.Length>0) { obj=Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.Wrap(this.contractType,obj); } returnobj; } returnnull; } privateMicrosoft.Practices.Unity.Configuration.UnityConfigurationSectionGetUnityConfigurationSection() { if(!string.IsNullOrEmpty(this.configFile)) { if(!sectionDict.ContainsKey(this.configFile)) { lock(lockObj) { if(!sectionDict.ContainsKey(this.configFile)) { Microsoft.Practices.Unity.Configuration.UnityConfigurationSectionunitySection=null; varfileMap=newSystem.Configuration.ExeConfigurationFileMap{ExeConfigFilename=System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory,this.configFile)}; System.Configuration.Configurationconfiguration=System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap,System.Configuration.ConfigurationUserLevel.None); unitySection=configuration==null?null:configuration.GetSection(Microsoft.Practices.Unity.Configuration.UnityConfigurationSection.SectionName)asMicrosoft.Practices.Unity.Configuration.UnityConfigurationSection; if(unitySection==null) returnnull; sectionDict.Add(this.configFile,unitySection); } } } returnsectionDict[this.configFile]; } returnSystem.Configuration.ConfigurationManager.GetSection(Microsoft.Practices.Unity.Configuration.UnityConfigurationSection.SectionName)asMicrosoft.Practices.Unity.Configuration.UnityConfigurationSection; } publicobjectGetInstance(System.ServiceModel.InstanceContextinstanceContext) { returnthis.GetInstance(instanceContext,null); } publicvoidReleaseInstance(System.ServiceModel.InstanceContextinstanceContext,objectinstance) { IDisposabledisposable=instanceasIDisposable; if(disposable!=null) { disposable.Dispose(); } instance=null; } #endregion } 复制代码
下面我们需要已Attribute方式贴在Contract上:
ViewCode publicclassELUnityBehaviorAttribute:Attribute,IContractBehavior { publicstringContainer { get; set; } publicstringConfigFile { get; set; } publicstringName { get; set; } #regionIContractBehavior成员 publicvoidAddBindingParameters(ContractDescriptioncontractDescription,ServiceEndpointendpoint,System.ServiceModel.Channels.BindingParameterCollectionbindingParameters) { } publicvoidApplyClientBehavior(ContractDescriptioncontractDescription,ServiceEndpointendpoint,System.ServiceModel.Dispatcher.ClientRuntimeclientRuntime) { } publicvoidApplyDispatchBehavior(ContractDescriptioncontractDescription,ServiceEndpointendpoint,System.ServiceModel.Dispatcher.DispatchRuntimedispatchRuntime) { dispatchRuntime.InstanceProvider=newELUnityInstanceProvider(contractDescription.ContractType,this.Container,this.ConfigFile,this.Name); } publicvoidValidate(ContractDescriptioncontractDescription,ServiceEndpointendpoint) { } #endregion } 复制代码
对于wcf同时我们也该支持配置文件扩展:
ViewCode publicclassELUnityBehaviorElement:BehaviorExtensionElement { [ConfigurationProperty("Container",IsRequired=false,DefaultValue="")] publicstringContainer { get; set; } [ConfigurationProperty("ConfigFile",IsRequired=false,DefaultValue="")] publicstringConfigFile { get; set; } [ConfigurationProperty("Name",IsRequired=false,DefaultValue="")] publicstringName { get; set; } protectedoverrideobjectCreateBehavior() { returnnewELUnityBehavior(this.Container,this.ConfigFile,this.Name); } publicoverrideTypeBehaviorType { get{returntypeof(ELUnityBehavior);} } } publicclassELUnityBehavior:IEndpointBehavior { publicstringContainer { get; set; } publicstringConfigFile { get; set; } publicstringName { get; set; } publicELUnityBehavior(stringcontainer,stringconfigFile,stringname) { this.Name=name; this.ConfigFile=configFile; this.Container=container; } #regionIEndpointBehavior成员 publicvoidAddBindingParameters(ServiceEndpointendpoint,System.ServiceModel.Channels.BindingParameterCollectionbindingParameters) { } publicvoidApplyClientBehavior(ServiceEndpointendpoint,System.ServiceModel.Dispatcher.ClientRuntimeclientRuntime) { } publicvoidApplyDispatchBehavior(ServiceEndpointendpoint,System.ServiceModel.Dispatcher.EndpointDispatcherendpointDispatcher) { endpointDispatcher.DispatchRuntime.InstanceProvider=newELUnityInstanceProvider(endpoint.Contract.ContractType,this.Container,this.ConfigFile,this.Name); } publicvoidValidate(ServiceEndpointendpoint) { } #endregion } 复制代码
目前我们已经简单实现了:看看测试:
ViewCode Contract: [ServiceContract()] [Green.WCFExtensions.ELUnityBehavior(Container="test",ConfigFile="App1.config")] publicinterfaceIHelloService { [OperationContract] stringSay(stringname); } Service: publicclassHelloService1:IHelloService { [Microsoft.Practices.Unity.Dependency("proxy")] publicIHelloServiceService { get; set; } #regionIHelloService成员 publicstringSay(stringname) { returnService.Say(name); } #endregion } publicclassHelloServiceProxy:IHelloService { #regionIHelloService成员 publicstringSay(stringname) { returnstring.Format("Hello:{0}",name); } #endregion } 复制代码
配置app1.config:
<registertype="WcfService.IHelloService,WcfService"mapTo="WcfService.HelloServiceProxy,WcfService"name="proxy"></register><registertype="WcfService.IHelloService,WcfService"mapTo="WcfService.HelloService1,WcfService"></register>
IOC,AOP博客参考:
AOP之PostSharp初见-OnExceptionAspect AOP之PostSharp2-OnMethodBoundaryAspect AOP之PostSharp3-MethodInterceptionAspect AOP之PostSharp4-实现类INotifyPropertyChanged植入 AOP之PostSharp5-LocationInterceptionAspect AOP之PostSharp6-EventInterceptionAspect AOP之PostSharp7-解决IOC 不能直接new问题,简化IOC开发和IOC对象LazyLoad http://www.cnblogs.com/whitewolf/category/312638.html 利用Attribute简化Unity框架IOC注入声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。