程序猿利器(四) wcf 自动生成终结点配置程序

               几年前搞wcf时发现每次新增业务封装类都要写对应的终结点配置,比较麻烦,研究了下 就自己写了个自动生成配置的代码。

               实现思路如下:

 

  • 反射加载程序集
  • 根据业务类特性识别程序集
  • 构造终结点配置string
  • 生成配置文件
         我的wcf 业务封装类都继承与public  abstract class Base ,所以加载特定的程序集后将继承自Base 的业务类识别出来然后逐一生成终结点配置信息即可。
 
        用的控制台来承载wcf
         
public class Program
    {
        static void Main()
        {

            //获取错误日志记录配置
            log4net.Config.XmlConfigurator.Configure();
            ILog InfoLog = LogManager.GetLogger("DBInfoLog");
           
            //从程序集中获取服务类型列表
            var servicelist = Assembly.GetExecutingAssembly().GetTypes().ToList().Where(x => x.BaseType == typeof(Base)).ToList();
            if (servicelist == null || servicelist.Count == 0)
                Console.WriteLine("没有要发布的wcf服务类型!");
            #region  生成配置的xml,发布时候需要注释掉
            获取app.config的目录
#if RELEASE
                try
                {
                    string path = AppDomain.CurrentDomain.BaseDirectory;
                    var removeString = path.Substring(path.LastIndexOf("bin"));
                    path = path.Replace(removeString, "App.config");
                    //如果能找到路径说明是开发模式下
                    if (File.Exists(path) == true)
                    {
                        MakeXmlConfig config = new MakeXmlConfig(path);
                        config.binding = "webHttpBinding";
                        config.endpointKind = "webHttpEndpoint";
                        config.behaviorConfiguration = "webHttpBehaviour";
                        config.TypeList = servicelist;
                        config.GetXml();
                    }
                }
                catch (Exception ex)
                {
                    Base.MakeErrorLog(ex);
                    return;
                }
#endif
            #endregion
            //服务存放字典
            Dictionary<string, WebServiceHost> serviceList = new Dictionary<string, WebServiceHost>();
            //记录服务名称
            string name;
            //服务对象
            WebServiceHost host;
            foreach (var item in servicelist)
            {
                name = item.Name;
                host = new WebServiceHost(item);
                serviceList.Add(name, host);
            }
            //遍历服务对象并打开服务
            try
            {
                foreach (var item in serviceList)
                    item.Value.Open();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                log4net.ILog log = log4net.LogManager.GetLogger("ApplicationInfoLog");
                log.Error(ex.Message, ex);
            }
            Console.Read();
        }
 其中 
MakeXmlConfig 定义如下
   <pre name="code" class="csharp">public class MakeXmlConfig
	{
        /// <summary>
        /// 服务名称
        /// </summary>
        public string serviceName { get; set; }
        /// <summary>
        /// 基地址 id地址
        /// </summary>
        public string BaseAddress { get; set; }
        /// <summary>
        /// 终结点传输类型名称
        /// </summary>
        public string endpointKind { get; set; }
        /// <summary>
        /// 绑定类型名称
        /// </summary>
        public string binding { get; set; }
        /// <summary>
        /// 终结点地址
        /// </summary>
        public string address { get; set; }
        /// <summary>
        /// 契约名称
        /// </summary>
        public string contract { get; set; }
        /// <summary>
        ///bindingConfiguration 属性
        /// </summary>
        public string bindingConfiguration { get; set; }
        /// <summary>
        /// behaviorConfiguration 属性
        /// </summary>
        public string behaviorConfiguration { get; set; }
        /// <summary>
        ///服务类型列表
        /// </summary>
        public List<Type> TypeList { get; set; }
        /// <summary>
        /// 要插入的xml结果列表
        /// </summary>
        List<string> xmlList { get; set; }
        /// <summary>
        /// 已经存在的服务列表
        /// </summary>
        List<string> ExistsList { get; set; }
        /// <summary>
        /// xml文件全路径
        /// </summary>
        string filename { get; set; }
        public MakeXmlConfig(string filename)
        {
            this.filename = filename;
            this.TypeList = new List<Type>();
            this.xmlList = new List<string>();
            this.ExistsList = new List<string>();
            this.BaseAddress = this.GetBaseAddress(this.filename);
        }
        /// <summary>
        /// 根据具体的服务类型进行拼接生成xml
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        string CreateXml(Type type)
        {
            var basenterfaceName = type.BaseType.GetInterfaces()[0].FullName;
            var sign="\"";
            serviceName = sign + type.FullName + sign;
            var bindingConfiguration = sign + this.bindingConfiguration + sign;
            var kind = sign + endpointKind + sign;
            var behaviorConfiguration = sign + this.behaviorConfiguration + sign;
            address =sign + BaseAddress + "/" + type.Name.Replace("Service", "") + sign;
            contract = sign + type.GetInterfaces().Where(x => x.FullName != basenterfaceName).ToList()[0].FullName + sign;
            return @"<service name="+serviceName+ @">
        <endpoint kind=" + kind + @" behaviorConfiguration="+behaviorConfiguration+@"
                address=" +address+@"  
                contract=" + contract + @"/>  "+Environment.NewLine+"</service>";
        }
        /// <summary>
        /// 获得要产生xml的列表
        /// </summary>
        public void GetXml()
        {
            this.GetXmlServicesList(this.filename);
            foreach (var item in TypeList)
            {
                if (this.ExistsList.Contains(item.FullName) == true)
                    continue;
                var result = this.CreateXml(item);
                this.xmlList.Add(result);
            }
            this.SaveXmlFile(this.filename);
        }
        /// <summary>
        ///获得已经存在的服务列表
        /// </summary>
        /// <param name="filename"></param>
        private void GetXmlServicesList(string filename)
        {
            XmlDocument xmlDoc = new XmlDocument();
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            XmlReader reader = XmlReader.Create(filename, settings);
            xmlDoc.Load(reader);
            XmlNode xn = xmlDoc.SelectSingleNode("descendant::services");
            if (xn == null)
                return;
            XmlNodeList xnl = xn.ChildNodes;
            foreach (XmlNode xnf in xnl)
            {
                XmlElement xe = (XmlElement)xnf;
                var attribute = xe.GetAttribute("name");
                this.ExistsList.Add(attribute);
            }
            reader.Close();
        }
        /// <summary>
        /// 保存列表
        /// </summary>
        private void SaveXmlFile(string filename)
        {
            //如果没有要写入的就返回
            if (this.xmlList == null || this.xmlList.Count == 0)
                return;
            StringBuilder result = new StringBuilder();
            //拼接要保存的配置文件
            foreach (var item in this.xmlList)
                result.Append(item+Environment.NewLine);
            //确认文件是否存在
            if (File.Exists(filename) == false)
            {
                Console.WriteLine("要设置的配置文件:{0}不存在,请确认!",filename);
                return;
            }
            FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite);
            StreamReader sm = new StreamReader(fs);
            //读取所有内容
            string txt = sm.ReadToEnd();
            sm.Close();
            fs.Close();
            //查找要插入的节点
            int index = txt.LastIndexOf("</services>");
            if (index == -1)
            {
                Console.WriteLine("请配置<services></services>节点");
                return;
            }
            txt= txt.Insert(index, result.ToString());
            System.IO.File.WriteAllText(filename, txt);
           
        }
        private string GetBaseAddress(string filename)
        { 
            string baseAddress ="";
            XmlDocument xmlDoc = new XmlDocument();
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            XmlReader reader = XmlReader.Create(filename, settings);
            xmlDoc.Load(reader);
            XmlNode node = xmlDoc.SelectSingleNode("//system.serviceModel//serviceHostingEnvironment//serviceActivations");//
            if (node != null && node.ChildNodes[0] != null)
            {
                baseAddress = node.ChildNodes[0].Attributes["relativeAddress"].Value;
            }
            else
            {
                Console.WriteLine("请配置基地址节点!");
            }
            reader.Close();
            return baseAddress;
        }
    }
 
 
         每次有新增业务类需要发布时,第一次运行控制台会自动重新生成一遍wcf 配置文件,然后再运行一遍即可测试,注意将wcf发布成windows 服务的时候参考如下代码
         
    protected override void OnStart(string[] args)
        {
            #if DEBUG        
            Debugger.Launch();    //Launches and attaches a debugger to the process.
            #endif
            //从程序集中获取服务类型列表
            //var servicelist = Assembly.GetExecutingAssembly().GetTypes().ToList().Where(x => x.BaseType == typeof(Base)).ToList();
            var servicelist = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "//EPSBX.WcfServices.Service.exe")
                .GetTypes().ToList().Where(x => x.BaseType ==typeof(Base)).ToList();
            if (servicelist == null)
                Console.WriteLine("没有要发布的wcf服务类型!");
            //服务存放字典
            Dictionary<string, WebServiceHost> serviceList = new Dictionary<string,WebServiceHost>();
            //记录服务名称
            string name;
            //服务对象
            WebServiceHost host;
            foreach (var item in servicelist)
            {
                name = item.Name;
                host = new WebServiceHost(item);
                serviceList.Add(name, host);
            }                                                            
            //Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory +"//EPS.WcfServices.Service.Interface.dll");
            //遍历服务对象并打开服务
            try
            {
                foreach (var item in serviceList)
                    item.Value.Open();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
               其中有个调试技巧,还是比较有用的,毕竟window 服务不太好调试
 #if DEBUG        
            Debugger.Launch();    //Launches and attaches a debugger to the process.
            #endif
  

如果您觉得我的文章对您有所帮助,欢迎扫码进行赞赏!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨4点5杀老大爷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值