SVG格式可以直接显示在网页上面,用来实现诸如统计Chart图表、流程图、组织结构图的功能。为了使图像可以下载下来以便于修改,可以将SVG转为Visio的vsd(x)格式。方法很简单,主要是使用Visio组件自带的方法,先打开svg文件,然后另存为vsd(x)文件。调用方法如下:
/// <summary> /// svg转vsd /// </summary> /// <param name="svgFn">svn文件名</param> /// <param name="desVsdFn">输出的vsd(x)文件名</param> private static void Svg2Vsd(string svgFn, string desVsdFn) { var app = ComObj.Create("Visio.Application"); try { app["Visible"] = new ComObj(false); var docs = app["Documents"]; short visOpenHidden = 64, visOpenRO = 2; var doc = docs.Call("OpenEx", svgFn, visOpenHidden + visOpenRO); doc.Call("SaveAs", desVsdFn); doc.Call("Close"); } finally { app.Call("Quit"); } }
这里用到了一个我自己写的ComObj类,其作用是为了便于通过反射来调用诸如Office之类的Com组件,并且使调用时的代码简洁明了!
为什么要用反射的方式来动态调用,而不采用直接引用Com组件的方式呢?主要是为了减少程序代码对Com组件的依赖耦合,从而方便代码的编译和发布部署。动态调用的方式,可以不添加组件的引用,就能编译、运行。如果服务器未安装这个Com组件,也可以进行直观的提示,而不是程序出错。
这个类的代码如下:
using System; using System.Reflection; namespace HZ.Common { /// <summary> /// 用于方便对Com对象的属性、方法调用 /// </summary> public class ComObj { public static ComObj Create(string progId) { var type = Type.GetTypeFromProgID(progId); if (type == null) { throw new Exception("服务器需要安装" + progId + "才能使用此功能"); } return new ComObj(Activator.CreateInstance(type)); } private object _val; /// <summary> /// 实际的值 /// </summary> public object Val { get { return _val; } } public ComObj(object comObject) { _val = comObject; } public ComObj Call(string mehtod, params object[] args) { if (_val == null) return null; var ret = _val.GetType().InvokeMember(mehtod, BindingFlags.InvokeMethod, null, _val, args); return new ComObj(ret); } public ComObj this[string property] { get { if (_val == null) return null; var ret = _val.GetType().InvokeMember(property, BindingFlags.GetProperty, null, _val, null); return new ComObj(ret); } set { if (_val != null) _val.GetType().InvokeMember(property, BindingFlags.SetProperty, null, _val, new object[] { value.Val }); } } } }