zoukankan      html  css  js  c++  java
  • WCF重写ServiceHost,实现独立配置文件

    有时我们需要将WCF的配置文件放在单独的配置文件中,而默认情况下WCF又是在web.config或app.config中去寻找服务配置。如果我们把配置文件放在另一个config文件中,如何让WCF知道呢?

    答案就是重写ServiceHost。在重写中告诉WCF配置文件的路径。

       public class MyServiceHost:ServiceHost
        {
            private string ConfigPath =System.AppDomain.CurrentDomain.BaseDirectory+ "MyApp.config";
    
            public MyServiceHost(Type serviceType, params Uri[] baseAddresses) :
                base(serviceType, baseAddresses)
            {
            }
    
            protected override void ApplyConfiguration()
            {
                // Check user config invalidation  
                if (!CheckConfigExist(ConfigPath))  
                {  
                    // Use default config  
                    base.ApplyConfiguration();  
                    return;  
                }  
                //base.ApplyConfiguration();  
                // Use user config  
                ExeConfigurationFileMap execfgMap = new ExeConfigurationFileMap();  
                // Set user config FilePath  
                execfgMap.ExeConfigFilename = ConfigPath;  
                // Config info  
                Configuration cfg = ConfigurationManager.OpenMappedExeConfiguration(execfgMap,ConfigurationUserLevel.None);  
                // Gets all service model config sections  
                ServiceModelSectionGroup servicemodelSections = ServiceModelSectionGroup.GetSectionGroup(cfg);  
                  
                // Find serivce section matched with the name "this.Description.ServiceType.FullName"   
                if (!ApplySectionInfo(this.Description.ServiceType.FullName,servicemodelSections))  
                {  
                    throw new Exception("ConfigApply Error : There is no endpoint existed in your config!! Please check your config file!");  
                }  
                this.ApplyMultiBehaviors(servicemodelSections);  
    
            }
    
            /// <summary>
            /// Check config file! 
            /// </summary>
            /// <param name="configpath"></param>
            /// <returns></returns>
            private bool CheckConfigExist(string configpath)
            {
                if (string.IsNullOrEmpty(configpath)) return false;
                if (!File.Exists(configpath)) return false;
                return true;
            }
    
            /// <summary>
            /// Apply section info
            /// </summary>
            /// <param name="serviceFullName"></param>
            /// <param name="servicemodelSections"></param>
            /// <returns></returns>
            private bool ApplySectionInfo(string serviceFullName, ServiceModelSectionGroup servicemodelSections)
            {
                // Check config sections (!including one section at least!)
                if (servicemodelSections == null) return false;
                // Service name can't be none!
                if (string.IsNullOrEmpty(serviceFullName)) return false;
                bool isElementExist = false;
                foreach (ServiceElement element in servicemodelSections.Services.Services)
                {
                    if (element.Name == serviceFullName)
                    {
                        // Find successfully & apply section info of config file
                        base.LoadConfigurationSection(element);
                        // Find service element successfully
                        isElementExist = true;
                        break;
                    }
                }
                return isElementExist;
            }
    
    
    
            /// <summary>
            /// Add behaviors
            /// </summary>
            /// <param name="servicemodelSections"></param>
            /// <returns></returns>
            private bool ApplyMultiBehaviors(ServiceModelSectionGroup servicemodelSections)
            {
                if (servicemodelSections == null) return false;
                foreach (ServiceBehaviorElement element in servicemodelSections.Behaviors.ServiceBehaviors)
                {
                    foreach (BehaviorExtensionElement behavior in element)
                    {
                        BehaviorExtensionElement behaviorEx = behavior;
                        object extention = behaviorEx.GetType().InvokeMember("CreateBehavior",
                            BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
                            null,
                            behaviorEx,
                            null);
                        if (extention == null) continue;
                        IServiceBehavior isb = (IServiceBehavior)extention;
                        //if (base.Description.Behaviors.Contains(isb)) break;
                        bool isbehaviorExisted = false;
                        foreach (IServiceBehavior i in base.Description.Behaviors)
                        {
                            if (i.GetType().Name == isb.GetType().Name)
                            {
                                isbehaviorExisted = true;
                                break;
                            }
                        }
                        if (isbehaviorExisted) break;
                        base.Description.Behaviors.Add((IServiceBehavior)extention);
                    }
                }
                return true;
            }
    
        }

    像上面那样,我们就把配置文件移到了MyApp.config。如果是控制台程序类的WCF服务就可以像下面那样来启动:

              using (MyServiceHost host=new MyServiceHost(typeof(Service1)))
                {
                    //... do something
                    host.Open();
                }

    而对于宿主是IIS的WCF服务,我们还需要再重写ServiceHostFactory:

     public class MyServiceHostFactory :  ServiceHostFactory
        {
            protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
            {
                return new MyServiceHost(serviceType, baseAddresses);
            }
        }

    然后在WCF服务的svc文件中,指定factory属性的值为我们重写的ServiceHostFactory:

    <%@ ServiceHost Factory="WcfService1.MyServiceHostFactory"  Language="C#" Debug="true" Service="WcfService1.Service1" CodeBehind="Service1.svc.cs" %>
  • 相关阅读:
    微信小程序 视频广告展示异常(“表情、壁纸”等页面,当视频广告与顶部区域重叠时,视频广告呈现透明状态,需重新设置视频广告的层级即可)
    Vue:The template root requires exactly one element.的解决办法
    Angular之ES6语法实现数组去重
    Java程序中的代理作用和应用场景及实现
    Hadoop hdfs副本存储和纠删码(Erasure Coding)存储优缺点
    Hadoop源码:namenode格式化和启动过程实现
    ssh免密登录设置后不生效
    递归查询子级元素,返回树形菜单数据
    mysql设置密码
    PX4飞行模式简单对比梳理
  • 原文地址:https://www.cnblogs.com/Gyoung/p/3651076.html
Copyright © 2011-2022 走看看