zoukankan      html  css  js  c++  java
  • 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), falseas 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博客参考:


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

  • 相关阅读:
    HDU 4472 Count DP题
    HDU 1878 欧拉回路 图论
    CSUST 1503 ZZ买衣服
    HDU 2085 核反应堆
    HDU 1029 Ignatius and the Princess IV
    UVa 11462 Age Sort
    UVa 11384
    UVa 11210
    LA 3401
    解决学一会儿累了的问题
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2343378.html
Copyright © 2011-2022 走看看