温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2020-06-12 00:39:38 阅读:1257 作者:破狼 栏目:编程语言
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

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

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×