好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

WCF利用企业库Unity框架的IOC层次解耦

WCF利用企业库Unity框架的IOC层次解耦

http://www.cnblogs.com/gannan/archive/2012/02/06/2339883.html

由于工作几个月来框架开发已经好久没写博客了,今天想抽点时间出来冒泡。在领域驱动开发中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的扩展:

View Code

public   class  ELUnityInstanceProvider : IInstanceProvider 
   { 
        private  Type contractType; 
        private   string  container; 
        private   string  configFile; 
        private   string  name; 
        private   static   object  lockObj =  new   object (); 
        private   static  Dictionary< string , UnityConfigurationSection> sectionDict =  new  Dictionary< string , UnityConfigurationSection>(); 

        public  ELUnityInstanceProvider(Type contractType,  string  container,  string  configFile,  string  name) 
       { 
            this .name = name; 
            this .configFile = configFile; 
            this .contractType = contractType; 
            this .container = container; 
       } 

        #region  IInstanceProvider 成员 

        public   object  GetInstance(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.Channels.Message message) 
       { 
           Microsoft.Practices.Unity.Configuration.UnityConfigurationSection unitySection = GetUnityConfigurationSection(); 

            if  (unitySection !=  null ) 
           { 
                var  container =  new  Microsoft.Practices.Unity.UnityContainer().LoadConfiguration(unitySection,  string .IsNullOrEmpty( this .container) ? unitySection.Containers.Default.Name :  this .container); 
                var  obj =  string .IsNullOrEmpty( this .name) ? container.Resolve( this .contractType) : container.Resolve( this .contractType,  this .name); 

                var  piabAtttr = obj.GetType().GetCustomAttributes( typeof (ELPolicyinjectionAttribute),  false )  as  ELPolicyinjectionAttribute[]; 
                if  (piabAtttr.Length >  0 ) 
               { 
                   obj = Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.Wrap( this .contractType, obj); 
               } 
                return  obj; 
           } 
            return   null ; 
       } 
        private  Microsoft.Practices.Unity.Configuration.UnityConfigurationSection GetUnityConfigurationSection() 
       { 
            if  (! string .IsNullOrEmpty( this .configFile)) 
           { 
                if  (!sectionDict.ContainsKey( this .configFile)) 
               { 
                    lock  (lockObj) 
                   { 
                        if  (!sectionDict.ContainsKey( this .configFile)) 
                       { 
                           Microsoft.Practices.Unity.Configuration.UnityConfigurationSection unitySection =  null ; 
                            var  fileMap =  new  System.Configuration.ExeConfigurationFileMap { ExeConfigFilename = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory,  this .configFile) }; 
                           System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, System.Configuration.ConfigurationUserLevel.None); 
                           unitySection = configuration ==  null  ?  null  : configuration.GetSection(Microsoft.Practices.Unity.Configuration.UnityConfigurationSection.SectionName)  as  Microsoft.Practices.Unity.Configuration.UnityConfigurationSection; 
                            if  (unitySection ==  null ) 
                                return   null ; 
                           sectionDict.Add( this .configFile, unitySection); 
                       } 
                   } 
               } 
                return  sectionDict[ this .configFile]; 
           } 

            return  System.Configuration.ConfigurationManager.GetSection(Microsoft.Practices.Unity.Configuration.UnityConfigurationSection.SectionName)  as  Microsoft.Practices.Unity.Configuration.UnityConfigurationSection; 

       } 

        public   object  GetInstance(System.ServiceModel.InstanceContext instanceContext) 
       { 
            return   this .GetInstance(instanceContext,  null ); 
       } 

        public   void  ReleaseInstance(System.ServiceModel.InstanceContext instanceContext,  object  instance) 
       { 
           IDisposable disposable = instance  as  IDisposable; 
            if  (disposable !=  null ) 
           { 
               disposable.Dispose(); 
           } 
           instance =  null ; 
       } 

        #endregion  
   }

复制代码

     下面我们需要已Attribute方式贴在Contract上:

View Code

public   class  ELUnityBehaviorAttribute : Attribute, IContractBehavior 
   { 
        public   string  Container 
       { 
            get ; 
            set ; 
       } 

        public   string  ConfigFile 
       { 
            get ; 
            set ; 
       } 

        public   string  Name 
       { 
            get ; 
            set ; 
       } 

        #region  IContractBehavior 成员 

        public   void  AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
       { 

       } 

        public   void  ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) 
       { 

       } 

        public   void  ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime) 
       { 
           dispatchRuntime.InstanceProvider =  new  ELUnityInstanceProvider(contractDescription.ContractType,  this .Container,  this .ConfigFile,  this .Name); 
       } 

        public   void  Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) 
       { 
       } 

        #endregion  
   }

复制代码

 

     对于wcf同时我们也该支持配置文件扩展:

View Code

public   class  ELUnityBehaviorElement : BehaviorExtensionElement 
   { 
       [ConfigurationProperty( " Container " , IsRequired =  false , DefaultValue =  "" )] 
        public   string  Container 
       { 
            get ; 
            set ; 
       } 

       [ConfigurationProperty( " ConfigFile " , IsRequired =  false , DefaultValue =  "" )] 
        public   string  ConfigFile 
       { 
            get ; 
            set ; 
       } 

       [ConfigurationProperty( " Name " , IsRequired =  false , DefaultValue =  "" )] 
        public   string  Name 
       { 
            get ; 
            set ; 
       } 

        protected   override   object  CreateBehavior() 
       { 
            return   new  ELUnityBehavior( this .Container,  this .ConfigFile,  this .Name); 
       } 

        public   override  Type BehaviorType 
       { 
            get  {  return   typeof (ELUnityBehavior); } 
       } 
   }

public   class  ELUnityBehavior : IEndpointBehavior 
   { 
        public   string  Container 
       { 
            get ; 
            set ; 
       } 

        public   string  ConfigFile 
       { 
            get ; 
            set ; 
       } 

        public   string  Name 
       { 
            get ; 
            set ; 
       } 

        public  ELUnityBehavior( string  container,  string  configFile,  string  name) 
       { 
            this .Name = name; 
            this .ConfigFile = configFile; 
            this .Container = container; 
       } 
        #region  IEndpointBehavior 成员 

        public   void  AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) 
       { 

       } 

        public   void  ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) 
       { 

       } 

        public   void  ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) 
       { 
           endpointDispatcher.DispatchRuntime.InstanceProvider =  new  ELUnityInstanceProvider(endpoint.Contract.ContractType,  this .Container,  this .ConfigFile,  this .Name); 
       } 

        public   void  Validate(ServiceEndpoint endpoint) 
       { 

       } 

        #endregion  
   }

复制代码

目前我们已经简单实现了:看看测试:

View Code

Contract:

   [ServiceContract()] 
   [Green.WCFExtensions.ELUnityBehavior(Container =  " test " , ConfigFile =  " App1.config " )]   
   public   interface  IHelloService 
  { 
      [OperationContract] 
       string  Say( string  name); 
  }

Service:

public   class  HelloService1 : IHelloService 
   { 
       [Microsoft.Practices.Unity.Dependency( " proxy " )] 
        public  IHelloService Service 
       { 
            get ; 
            set ; 
       } 

        #region  IHelloService 成员 
           public   string  Say( string  name) 
       { 
                      return  Service.Say(name); 

       } 

        #endregion  
   } 

    public   class  HelloServiceProxy : IHelloService 
   { 
        #region  IHelloService 成员 
        public   string  Say( string  name) 
       { 
            return   string .Format( " Hello:{0} " , name); 
       } 

        #endregion  
   }

复制代码

配置app1.config:

< register  type ="WcfService.IHelloService,WcfService"  mapTo ="WcfService.HelloServiceProxy,WcfService"   name ="proxy" >   </ register >  
< register  type ="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注入


作者: 破  狼  
出处: http://www.cnblogs.com/whitewolf/  
本文版权归作者和博客园、CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中- 博客园--破狼 和 CSDN--野狼 。

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于WCF利用企业库Unity框架的IOC层次解耦的详细内容...

  阅读:39次