程序猿利器(四) wcf 自动生成终结点配置程序
2015-08-17 23:34
661 查看
几年前搞wcf时发现每次新增业务封装类都要写对应的终结点配置,比较麻烦,研究了下 就自己写了个自动生成配置的代码。
实现思路如下:
反射加载程序集
根据业务类特性识别程序集
构造终结点配置string
生成配置文件
我的wcf 业务封装类都继承与publicabstract class Base ,所以加载特定的程序集后将继承自Base 的业务类识别出来然后逐一生成终结点配置信息即可。
用的控制台来承载wcf
每次有新增业务类需要发布时,第一次运行控制台会自动重新生成一遍wcf 配置文件,然后再运行一遍即可测试,注意将wcf发布成windows 服务的时候参考如下代码
实现思路如下:
反射加载程序集
根据业务类特性识别程序集
构造终结点配置string
生成配置文件
我的wcf 业务封装类都继承与publicabstract 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
相关文章推荐
- CSS jQuery 图片全屏切换
- 再探OAuth2
- matlab实现MSER(最大极值稳定区域)来进行文本定位
- 在linux下把Tomcat注册成service
- Say Cheese
- 华为荣耀7“耗电门”始末,北研所兄弟们的双年终奖还有吗?
- LintCode (9)Fizz Buzz
- C++的struct和union
- 九度 Online Judge 算法 刷题 题目1369:字符串的排列
- 每天五个java相关面试题(3)
- 嵌入式工程师考试总结 fork()函数
- C++的struct和union
- 最高分数记录
- 关闭线程的一些问题
- JAVASCRIPT
- hibernate 级联的选项
- Linux下把U盘格式化为fat32
- Android(客户端)通过socket与QT(服务端)通信
- 合唱队
- Linux下把U盘格式化为fat32