由于工作几个月来框架开发已经好久没写博客了,今天想抽点时间出来冒泡。在领域驱动开发中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:
IOC,AOP博客参考:
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。