C#远程调用WebService

发布时间 2023-09-06 11:17:53作者: 多可悲
        /// <summary>
        /// 远程调用WebService
        /// </summary>
        /// <param name="url">以wsdl结尾的url地址</param>
        /// <param name="method">要调用的方法名</param>
        /// <param name="args">参数,按顺序传递</param>
        /// <returns></returns>
        public static object InvokeWebService(string url, string method, params object[] args)
        {
            var @namespace = new CodeNamespace(nameof(InvokeWebService));
            var client = new System.Net.WebClient();
            var stream = client.OpenRead(url);
            var description = ServiceDescription.Read(stream);
            var descriptionImporter = new ServiceDescriptionImporter();
            descriptionImporter.AddServiceDescription(description, string.Empty, string.Empty);
            var compileUnit = new CodeCompileUnit();
            compileUnit.Namespaces.Add(@namespace);
            var clientProtocol = new DiscoveryClientProtocol();
            clientProtocol.DiscoverAny(url);
            clientProtocol.ResolveAll();
            foreach (var osd in clientProtocol.Documents.Values)
            {
                if (osd is ServiceDescription) descriptionImporter.AddServiceDescription((ServiceDescription)osd, null, null); ;
                if (osd is XmlSchema) descriptionImporter.Schemas.Add((XmlSchema)osd);
            }
            descriptionImporter.Import(@namespace, compileUnit);
            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true
            };
            compilerParameters.ReferencedAssemblies.Add("System.dll");
            compilerParameters.ReferencedAssemblies.Add("System.XML.dll");
            compilerParameters.ReferencedAssemblies.Add("System.Web.Services.dll");
            compilerParameters.ReferencedAssemblies.Add("System.Data.dll");
            var compilerResults = new Microsoft.CSharp.CSharpCodeProvider().CompileAssemblyFromDom(compilerParameters, compileUnit);
            if (compilerResults.Errors.HasErrors)
            {
                var sb = new StringBuilder();
                foreach (var ce in compilerResults.Errors)
                {
                    sb.Append(ce.ToString());
                    sb.Append(Environment.NewLine);
                }
                throw new Exception(sb.ToString());
            }

            var type = compilerResults.CompiledAssembly.GetType($"{@namespace}.{description.Services[0].Name}", true, true);
            var mi = type.GetMethod(method);
            var paramsInfo = mi.GetParameters();
            if (args.Length != paramsInfo.Length)
            {
                throw new Exception("提供的参数数量错误");
            }
            var paramArr = new object[args.Length];
            for (int i = 0; i < args.Length; i++)
            {
                var pType = paramsInfo[i].ParameterType;

                if (pType.IsValueType || typeof(string).Equals(pType))
                {
                    paramArr[i] = Convert.ChangeType(args[i], pType);
                }
                else
                {
                    if (args[i] is string)
                    {
                        paramArr[i] = Newtonsoft.Json.JsonConvert.DeserializeObject(args[i].ToString(), pType);
                    }
                    else
                    {
                        throw new Exception($"提供的参数类型有误,参数需要{pType.Name}类型,而传的是{args[i].GetType().Name}类型");
                    }
                }
            }
            return mi.Invoke(Activator.CreateInstance(type), paramArr);
        }