由于工作几个月来框架开发已经好久没写博客了,今天想抽点时间出来冒泡。在领域驱动开发中SOA已经成为我们开发的主流技术,在面对当前众多的UI框架选择(asp.net mvc,silverlight,wpf,winform,wp7等一些列甚至跨语言),我们能够重用和抽象的业务逻辑是不会变化的,为了屏蔽这些UI的复杂性和差异性,我们可能会采用诸如wcf soap的服务发布。再说在领域驱动开发中我们肯定会把各个逻辑分层次隔离解除耦合,这就出现了N层架构,在于我们的每一层次之间的耦合度当前流程的解决方案IOC框架,以及业务解耦AOP。这里要解决的是SOA框架WCF和IOC框架的结合。
网站建设公司,为您提供网站建设,网站制作,网页设计及定制网站建设服务,专注于企业网站建设,高端网页制作,对成都凿毛机等多个行业拥有丰富的网站建设经验的网站建设公司。专业网站设计,网站优化推广哪家好,专业网站推广优化,H5建站,响应式网站。
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
sectionDict = new Dictionary (); - 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:
IOC,AOP博客参考: