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();
}
}
}