using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RGDWCSServices.Common
{
    public static class WebServiceHelper
    {
        /// <summary>动态调用webService
        /// 动态调用webService
        /// </summary>
        /// <param name="sUrl">地址</param>
        /// <param name="sClassName">类名</param>
        /// <param name="sMethodName">方法名</param>
        /// <param name="args">参数</param>
        /// <param name="sResult">返回结果</param>
        /// <returns></returns>
        public static bool Invoke(string sUrl, string sClassName, string sMethodName, object[] args, out string sResult)
        {
            bool bResult = true;

            sResult = string.Empty;

            if (string.IsNullOrEmpty(sClassName))
            {
                sClassName = GetClassName(sUrl);
            }

            try
            {
                System.Net.WebClient wc = new System.Net.WebClient();
                System.IO.Stream stream = wc.OpenRead(sUrl);
                //System.IO.Stream stream = wc.OpenRead(sUrl + "?WSDL");
                System.Web.Services.Description.ServiceDescription sd = System.Web.Services.Description.ServiceDescription.Read(stream);
                System.Web.Services.Description.ServiceDescriptionImporter sdi = new System.Web.Services.Description.ServiceDescriptionImporter();
                sdi.AddServiceDescription(sd, "", "");
                System.CodeDom.CodeNamespace cn = new System.CodeDom.CodeNamespace();
                System.CodeDom.CodeCompileUnit ccu = new System.CodeDom.CodeCompileUnit();
                ccu.Namespaces.Add(cn);
                sdi.Import(cn, ccu);

                Microsoft.CSharp.CSharpCodeProvider csc = new Microsoft.CSharp.CSharpCodeProvider();
#pragma warning disable CS0618 // 类型或成员已过时
                System.CodeDom.Compiler.ICodeCompiler icc = csc.CreateCompiler();
#pragma warning restore CS0618 // 类型或成员已过时

                System.CodeDom.Compiler.CompilerParameters cplist = new System.CodeDom.Compiler.CompilerParameters();
                cplist.GenerateExecutable = false;
                cplist.GenerateInMemory = true;
                cplist.ReferencedAssemblies.Add("System.dll");
                cplist.ReferencedAssemblies.Add("System.XML.dll");
                cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
                cplist.ReferencedAssemblies.Add("System.Data.dll");

                //CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
                //CompilerResults cr = provider.CompileAssemblyFromDom(cplist, ccu);

                System.CodeDom.Compiler.CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
                if (true == cr.Errors.HasErrors)
                {
                    System.Text.StringBuilder sb = new System.Text.StringBuilder();
                    foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
                    {
                        sb.Append(ce.ToString());
                        sb.Append(System.Environment.NewLine);
                    }
                    throw new Exception(sb.ToString());
                }
                System.Reflection.Assembly assembly = cr.CompiledAssembly;

                Type t = assembly.GetType(sClassName, true, true);
                object obj = Activator.CreateInstance(t);
                ((System.Web.Services.Protocols.WebClientProtocol)(obj)).Timeout = 120000;
                System.Reflection.MethodInfo mi = t.GetMethod(sMethodName);
                sResult = mi.Invoke(obj, args) as string;
            }
            catch (Exception ex)
            {
                bResult = false;
                sResult = ex.ToString();
            }

            return bResult;
        }

        private static string GetClassName(string url)
        {
            string[] parts = url.Split('/');

            string[] pps = parts[parts.Length - 1].Split('?');
            if (pps[0].Contains(".asmx"))
            {
                pps[0] = pps[0].Substring(0, pps[0].IndexOf('.'));
            }
            return pps[0];
        }
    }
}
