View Code
  1 using System.IO;
2 using System.Net;
3 using System.CodeDom;
4 using System.CodeDom.Compiler;
5 using System.Web.Services;
6 using System.Web.Services.Description;
7 using System.Web.Services.Protocols;
8 using System.Xml.Serialization;
9 using System.Web.Services.Discovery;
10 using System.Xml.Schema;
11 using System.Text;
12 using System;
13 using System.Security.Cryptography;
14 using System.Reflection;
15
16 namespace SK.WebServices
17 {
18 /// <summary>
19 /// web服务代理类,兼容java发布的webserive
20 /// </summary>
21 public class WSDynamicProxy
22 {
23 #region Variables and Properties
24
25 /// <summary>
26 /// web服务名称
27 /// </summary>
28 private string _wsName = string.Empty;
29
30 /// <summary>
31 /// 代理类类型名称
32 /// </summary>
33 private Type _typeName = null;
34
35 /// <summary>
36 /// 程序集名称
37 /// </summary>
38 private string _assName = string.Empty;
39
40 /// <summary>
41 /// web服务地址
42 /// </summary>
43 private string _wsdlUrl = string.Empty;
44
45 /// <summary>
46 /// 代理类所在程序集路径
47 /// </summary>
48 private string _assPath = string.Empty;
49
50 /// <summary>
51 /// 代理类的实例
52 /// </summary>
53 private object _instance = null;
54
55 /// <summary>
56 /// 代理类的实例
57 /// </summary>
58 private object Instance
59 {
60 get
61 {
62 if (_instance == null)
63 {
64 _instance = Activator.CreateInstance(_typeName);
65 return _instance;
66
67 }
68 else
69 return _instance;
70 }
71 }
72 #endregion
73
74 public WSDynamicProxy(string wsdlUrl, string wsName)
75 {
76 this._wsdlUrl = wsdlUrl;
77 this._wsName = wsName;
78 this._assName = string.Format("ZTENetNumenU36.WebServices.{0}", wsName);
79 this._assPath = Path.GetTempPath() + this._assName + getMd5Sum(this._wsdlUrl) + ".dll";
80 CreateUSSServiceAssembly();
81 }
82
83 #region public method
84 /// <summary>
85 /// 得到WSDL信息,生成本地代理类并编译为DLL
86 /// </summary>
87 public void CreateUSSServiceAssembly()
88 {
89 if (this.checkCache())
90 {
91 this.initTypeName();
92 return;
93 }
94
95 if (string.IsNullOrEmpty(this._wsdlUrl))
96 {
97 return;
98 }
99
100 try
101 {
102 // 使用WebClient下载 WSDL 信息
103 WebClient web = new WebClient();
104 Stream stream = web.OpenRead(this._wsdlUrl);
105
106 // 创建和格式化WSDL文档
107 ServiceDescription description = ServiceDescription.Read(stream);
108 // 创建客户端代理代理类
109 ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
110
111 importer.ProtocolName = "Soap";
112 importer.Style = ServiceDescriptionImportStyle.Client; //生成客户端代理
113 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
114 //添加WSDL文档
115 importer.AddServiceDescription(description, null, null);
116
117 // 使用 CodeDom 编译客户端代理类
118 CodeNamespace nmspace = new CodeNamespace(_assName); //为代理类添加命名空间
119 CodeCompileUnit unit = new CodeCompileUnit();
120
121 unit.Namespaces.Add(nmspace);
122
123 this.checkForImports(this._wsdlUrl, importer);
124
125 ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
126
127 CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
128
129 CompilerParameters parameter = new CompilerParameters();
130 parameter.ReferencedAssemblies.Add("System.dll");
131 parameter.ReferencedAssemblies.Add("System.XML.dll");
132 parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
133 parameter.ReferencedAssemblies.Add("System.Data.dll");
134 parameter.GenerateExecutable = false;
135 parameter.GenerateInMemory = false;
136 parameter.IncludeDebugInformation = false;
137
138 CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);
139 provider.Dispose();
140 if (result.Errors.HasErrors)
141 {
142 string errors = string.Format(@"Build failed: {0} errors", result.Errors.Count);
143 foreach (CompilerError error in result.Errors)
144 {
145 errors += error.ErrorText;
146 }
147 throw new Exception(errors);
148 }
149
150 this.copyTempAssembly(result.PathToAssembly);
151 this.initTypeName();
152 }
153 catch (Exception e)
154 {
155 throw new Exception(e.Message);
156 }
157 }
158
159 /// <summary>
160 /// 执行代理类指定方法,有返回值
161 /// </summary>
162 /// <param name="methodName">方法名称</param>
163 /// <param name="param">参数</param>
164 /// <returns>返回值</returns>
165 public object ExecuteQuery(string methodName, object[] param)
166 {
167 object rtnObj = null;
168 if (this._typeName != null)
169 {
170 MethodInfo method = this._typeName.GetMethod(methodName);
171 rtnObj = method.Invoke(Instance, param);
172 }
173 else
174 {
175 throw new Exception(string.Format("The Web Service '{0}' is not available!", this._wsName));
176 }
177 return rtnObj;
178 }
179
180 /// <summary>
181 /// 执行代理类指定方法,无返回值
182 /// </summary>
183 /// <param name="methodName">方法名称</param>
184 /// <param name="param">参数</param>
185 public void ExecuteNoQuery(string methodName, object[] param)
186 {
187 if (this._typeName != null)
188 {
189 MethodInfo method = this._typeName.GetMethod(methodName);
190 method.Invoke(Instance, param);
191 }
192 else
193 {
194 throw new Exception(string.Format("The Web Service '{0}' is not available!", this._wsName));
195 }
196 }
197 #endregion
198
199 #region private method
200 /// <summary>
201 /// 得到代理类类型名称
202 /// </summary>
203 private void initTypeName()
204 {
205 Assembly serviceAsm = Assembly.LoadFrom(this._assPath);
206 Type[] types = serviceAsm.GetTypes();
207 string objTypeName = "";
208 foreach (Type t in types)
209 {
210 if (t.BaseType == typeof(SoapHttpClientProtocol))
211 {
212 objTypeName = t.Name;
213 break;
214 }
215 }
216 _typeName = serviceAsm.GetType(this._assName + "." + objTypeName);
217 }
218
219
220 /// <summary>
221 /// 根据web service文档架构向代理类添加ServiceDescription和XmlSchema
222 /// </summary>
223 /// <param name="baseWSDLUrl">web服务地址</param>
224 /// <param name="importer">代理类</param>
225 private void checkForImports(string baseWSDLUrl, ServiceDescriptionImporter importer)
226 {
227 DiscoveryClientProtocol dcp = new DiscoveryClientProtocol();
228 dcp.DiscoverAny(baseWSDLUrl);
229 dcp.ResolveAll();
230 foreach (object osd in dcp.Documents.Values)
231 {
232 if (osd is ServiceDescription) importer.AddServiceDescription((ServiceDescription)osd, null, null); ;
233 if (osd is XmlSchema) importer.Schemas.Add((XmlSchema)osd);
234 }
235 }
236
237 /// <summary>
238 /// 复制程序集到指定路径
239 /// </summary>
240 /// <param name="pathToAssembly">程序集路径</param>
241 private void copyTempAssembly(string pathToAssembly)
242 {
243 File.Copy(pathToAssembly, this._assPath);
244 }
245
246 private string getMd5Sum(string str)
247 {
248 Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
249
250 byte[] unicodeText = new byte[str.Length * 2];
251 enc.GetBytes(str.ToCharArray(), 0, str.Length, unicodeText, 0, true);
252
253 MD5 md5 = new MD5CryptoServiceProvider();
254 byte[] result = md5.ComputeHash(unicodeText);
255
256 StringBuilder sb = new StringBuilder();
257 for (int i = 0; i < result.Length; i++)
258 {
259 sb.Append(result[i].ToString("X2"));
260 }
261 return sb.ToString();
262 }
263
264 /// <summary>
265 /// 是否已经存在该程序集
266 /// </summary>
267 /// <returns>false:不存在该程序集,true:已经存在该程序集</returns>
268 private bool checkCache()
269 {
270 if (File.Exists(this._assPath))
271 {
272 return true;
273 }
274
275 return false;
276 }
277
278
279 #endregion
280 }
281 }
 posted on 2011-12-02 22:45  k&H  阅读(494)  评论(0编辑  收藏  举报