using System; using System.CodeDom; using System.CodeDom.Compiler; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Web.Services; using System.Web.Services.Description; using System.Web.Services.Protocols; using System.Xml.Serialization; namespace SysBaseLibs { public class DynamicWebService { string _Address = ""; /// /// WebService 的地址 /// public string Address { get { return _Address; } set { _Address = value; } } string _ProtocolName = "Soap"; /// /// 协议 默认 Soap /// public string ProtocolName { get { return _ProtocolName; } set { _ProtocolName = value; } } string _nmspaceName = "Sonics.Web.WebService.Dyn"; /// /// 命名空间 默认 Sonics.Web.WebService.Dyn /// public string NmspaceName { get { return _nmspaceName; } set { _nmspaceName = value; } } /// /// 动态调用WebService /// /// 类名称 /// 方法名称 /// 方法参数 /// 返回的结果 public object GetWebServiceData(string ClassName, string MethodName, object[] MethodParameter) { // 1. 使用 WebClient 下载 WSDL 信息。 WebClient web = new WebClient(); Stream stream = web.OpenRead(_Address + "?WSDL"); // 2. 创建和格式化 WSDL 文档。 ServiceDescription description = ServiceDescription.Read(stream); // 3. 创建客户端代理代理类。 ServiceDescriptionImporter importer = new ServiceDescriptionImporter(); importer.ProtocolName = _ProtocolName; // 指定访问协议。 importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync; importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。 // 4. 使用 CodeDom 编译客户端代理类。 CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。 nmspace.Name = _nmspaceName; CodeCompileUnit unit = new CodeCompileUnit(); unit.Namespaces.Add(nmspace); ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); CompilerParameters parameter = new CompilerParameters(); parameter.GenerateExecutable = false; parameter.GenerateInMemory = true; parameter.ReferencedAssemblies.Add("System.dll"); parameter.ReferencedAssemblies.Add("System.XML.dll"); parameter.ReferencedAssemblies.Add("System.Web.Services.dll"); parameter.ReferencedAssemblies.Add("System.Data.dll"); CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit); if (result.Errors.HasErrors) { foreach (CompilerError loError in result.Errors) { if (loError.IsWarning) { ThreadLog.LogWarning("FileName:" + loError.FileName); ThreadLog.LogWarning("Line:" + loError.Line + " ErrorText:" + loError.ErrorText); } else { ThreadLog.LogErr("FileName:" + loError.FileName); ThreadLog.LogErr("Line:" + loError.Line + " ErrorText:" + loError.ErrorText); } } return null; } // 5. 使用 Reflection 调用 WebService。 Assembly asm = result.CompiledAssembly; Type t = asm.GetType(_nmspaceName + "." + ClassName);// 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。 object o = Activator.CreateInstance(t); MethodInfo method = t.GetMethod(MethodName); return method.Invoke(o, MethodParameter); } /// /// 动态调用WebService,生成dll /// /// 类名称 /// 方法名称 /// 方法参数 /// 动态生成的类名称 /// 返回的结果 public object GetWebServiceData(string ClassName, string MethodName, object[] MethodParameter, string dllName) { // 1. 使用 WebClient 下载 WSDL 信息。 WebClient web = new WebClient(); Stream stream = web.OpenRead(_Address + "?WSDL"); // 2. 创建和格式化 WSDL 文档。 ServiceDescription description = ServiceDescription.Read(stream); // 3. 创建客户端代理代理类。 ServiceDescriptionImporter importer = new ServiceDescriptionImporter(); importer.ProtocolName = _ProtocolName; // 指定访问协议。 importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync; importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。 // 4. 使用 CodeDom 编译客户端代理类。 CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。 nmspace.Name = _nmspaceName; CodeCompileUnit unit = new CodeCompileUnit(); unit.Namespaces.Add(nmspace); ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); CompilerParameters parameter = new CompilerParameters(); parameter.GenerateExecutable = false; parameter.OutputAssembly = dllName; // 可以指定你所需的任何文件名。 parameter.ReferencedAssemblies.Add("System.dll"); parameter.ReferencedAssemblies.Add("System.XML.dll"); parameter.ReferencedAssemblies.Add("System.Web.Services.dll"); parameter.ReferencedAssemblies.Add("System.Data.dll"); CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit); if (result.Errors.HasErrors) { foreach (CompilerError loError in result.Errors) { if (loError.IsWarning) { ThreadLog.LogWarning("FileName:" + loError.FileName); ThreadLog.LogWarning("Line:" + loError.Line + " ErrorText:" + loError.ErrorText); } else { ThreadLog.LogErr("FileName:" + loError.FileName); ThreadLog.LogErr("Line:" + loError.Line + " ErrorText:" + loError.ErrorText); } } return null; } Assembly asm = Assembly.LoadFrom(dllName); Type t = asm.GetType(_nmspaceName + "." + ClassName); object o = Activator.CreateInstance(t); MethodInfo method = t.GetMethod(MethodName); return method.Invoke(o, MethodParameter); } /// /// 获取客户端代理类源代码 /// /// public string GetServerAgentCode() { WebClient web = new WebClient(); Stream stream = web.OpenRead(_Address + "?WSDL"); // 2. 创建和格式化 WSDL 文档。 ServiceDescription description = ServiceDescription.Read(stream); // 3. 创建客户端代理代理类。 ServiceDescriptionImporter importer = new ServiceDescriptionImporter(); importer.ProtocolName = _ProtocolName; // 指定访问协议。 importer.Style = ServiceDescriptionImportStyle.Client; // 生成客户端代理。 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync; importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。 // 4. 使用 CodeDom 编译客户端代理类。 CodeNamespace nmspace = new CodeNamespace(); // 为代理类添加命名空间,缺省为全局空间。 nmspace.Name = _nmspaceName; CodeCompileUnit unit = new CodeCompileUnit(); unit.Namespaces.Add(nmspace); ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); // 5. 保存源代码到文件。当然,你也可以直接保存到内存字符串中。 // TextWriter writer = File.CreateText("test.cs"); // 指定你所需的源代码文件名。 StringWriter writer = new StringWriter(); provider.GenerateCodeFromCompileUnit(unit, writer, null); StringBuilder sb = writer.GetStringBuilder(); writer.Close(); return sb.ToString(); } } }