发一个一直以来最关心的解决方案,动态对所有WebService,WCF等Web服务进行调用

一直来,工作中最大的问题,跟第三方做接口,每次非得第三饭给个WSDL文件,通过工具转换成代理类来调用,

目前提供此此方法,完全参照微软官网。实现只需输入服务地址即可进行调用,或者生成本地代理类;需要的小伙伴可以参考一下:

一下方法通过封装可以精简,本人工作比较忙就未进行封装直接复制粘贴,修改一下,需要的,有时间的自己整理:

其中用到的类Gaofajin.xxxx起始在此代码不多于,也就记录日志,不想用的直接删除相关代码即可,不影响本类功能,需要的可以到

Nugut获取!,此类仅个人用,觉得不好用,不够技术的请不要攻击!!!!谢谢合作!!!!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.ServiceModel;
using System.Net;
using System.IO;
using System.Reflection;
using Gaofajin.LogWriter;
using Gaofajin.ExtendsMethod;
using System.ServiceModel.Description;
using System.Runtime.Serialization;
using System.Collections.ObjectModel;
using System.Web.DynamicData;
namespace Gaofajin.Net
{
   public class WcfCaller
    {
        private static string HandleUrl(string url)
        {
            if (url.EndsWith("?wsdl"))
            {
                return url;
            }
            else
            {
                return url + "?wsdl";
            }
        }
        //static  string  GetConfigName(string fieName)
        //{
        //    return fieName.Substring(0, fieName.LastIndexOf('.')+1)+"config";
        //}
        /// <summary>
        /// 生成代理类及其配置文件
        /// </summary>
        /// <param name="uri">服务地址</param>
        /// <param name="fileName">文件名</param>
        public static void GetServiceProxyClassFile(string uri,string fileName= "WebService.cs")
        {
          uri=  HandleUrl(uri);
            MetadataExchangeClient client = new MetadataExchangeClient(new Uri(uri), MetadataExchangeClientMode.HttpGet)
            {
                ResolveMetadataReferences = true
            };
            MetadataSet metadata = client.GetMetadata();
            WsdlImporter wsdl = new WsdlImporter(metadata);
            ServiceContractGenerator generator = new ServiceContractGenerator();
            XsdDataContractImporter imp;
            if (!wsdl.State.TryGetValue(typeof(XsdDataContractImporter),out object obj))
            {
                imp = new XsdDataContractImporter
                {
                    Options = new ImportOptions()
                };
                wsdl.State.Add(typeof(XsdDataContractImporter), imp);
            }else
            {
                imp = (XsdDataContractImporter)obj;
                if(imp.Options==null)
                {
                    imp.Options = new ImportOptions();
                }
            }
            System.Collections.ObjectModel.Collection<ContractDescription> a = wsdl.ImportAllContracts();
            wsdl.ImportAllEndpoints();
            wsdl.ImportAllBindings();
            foreach(var m in a)
            {
                generator.GenerateServiceContractType(m);
            }
           
            if (generator.Errors.Count!=0)
            {
                foreach (var l in generator.Errors)
                {
                    TxtLog.Instance.WriteLineToFile("动态调用发生错误:"+l,LogType.Error);
                }
            }
            //写文件
            System.CodeDom.Compiler.CodeGeneratorOptions options = new CodeGeneratorOptions
            {
                BracingStyle = "C"
            };
            CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
            System.CodeDom.Compiler.IndentedTextWriter writer = new IndentedTextWriter(new StreamWriter(fileName));
            provider.GenerateCodeFromCompileUnit(generator.TargetCompileUnit, writer, options);
            writer.Close();
        }
        /// <summary>
        /// 单独获取某服务的服务调用配置文件
        /// </summary>
        /// <param name="uri">服务地址</param>
        /// <param name="fileName">生成的文件名称</param>
        //public static void GetServiceConfigFile(string uri, string fileName = "WebService.config")
        //{
        //    uri = HandleUrl(uri);
        //    MetadataExchangeClient client = new MetadataExchangeClient(new Uri(uri), MetadataExchangeClientMode.HttpGet);
        //    client.ResolveMetadataReferences = true;
        //    MetadataSet metadata = client.GetMetadata();
        //    WsdlImporter wsdl = new WsdlImporter(metadata);
        //    ServiceContractGenerator generator = new ServiceContractGenerator();
        //    object obj;
        //    XsdDataContractImporter imp;
        //    if (!wsdl.State.TryGetValue(typeof(XsdDataContractImporter), out obj))
        //    {
        //        imp = new XsdDataContractImporter();
        //        imp.Options = new ImportOptions();
        //        wsdl.State.Add(typeof(XsdDataContractImporter), imp);
        //    }
        //    else
        //    {
        //        imp = (XsdDataContractImporter)obj;
        //        if (imp.Options == null)
        //        {
        //            imp.Options = new ImportOptions();
        //        }
        //    }
        //    System.Collections.ObjectModel.Collection<ContractDescription> a = wsdl.ImportAllContracts();
        //    wsdl.ImportAllEndpoints();
        //    System.Collections.ObjectModel.Collection<System.ServiceModel.Channels.Binding> b = wsdl.ImportAllBindings();
        //    foreach (var m in a)
        //    {
        //        generator.GenerateServiceContractType(m);
        //    }
        //    if (generator.Errors.Count != 0)
        //    {
        //        foreach (var l in generator.Errors)
        //        {
        //            TxtLog.Instance.WriteLineToFile("动态调用发生错误:" + l, LogType.Error);
        //        }
        //    }
        //    generator.Configuration.SaveAs(fileName);
        //}
        /// <summary>
        /// 动态调用WebService
        /// </summary>
        /// <typeparam name="T">返回值类型</typeparam>
        /// <param name="uri">服务 地址</param>
        /// <param name="MethodName">要调用的方法名称</param>
        /// <param name="para">参数</param>
        /// <returns>返回调用结果</returns>
        public static T DynamicCallService<T>(string uri,string MethodName,params object[]para)
        {
            uri = HandleUrl(uri);
            MetadataExchangeClient client = new MetadataExchangeClient(new Uri(uri), MetadataExchangeClientMode.HttpGet)
            {
                ResolveMetadataReferences = true
            };
            MetadataSet metadata = client.GetMetadata();
            WsdlImporter wsdl = new WsdlImporter(metadata);
            ServiceContractGenerator generator = new ServiceContractGenerator();
            XsdDataContractImporter imp;
            if (!wsdl.State.TryGetValue(typeof(XsdDataContractImporter), out object obj))
            {
                imp = new XsdDataContractImporter
                {
                    Options = new ImportOptions()
                };
                wsdl.State.Add(typeof(XsdDataContractImporter), imp);
            }
            else
            {
                imp = (XsdDataContractImporter)obj;
                if (imp.Options == null)
                {
                    imp.Options = new ImportOptions();
                }
            }
            System.Collections.ObjectModel.Collection<ContractDescription> a = wsdl.ImportAllContracts();
            wsdl.ImportAllEndpoints();
            System.ServiceModel.Channels.Binding b = wsdl.ImportAllBindings()[0];
            foreach (var m in a)
            {
                generator.GenerateServiceContractType(m);
            }
            if (generator.Errors.Count != 0)
            {
                foreach (var l in generator.Errors)
                {
                    TxtLog.Instance.WriteLineToFile("动态调用发生错误:" + l, LogType.Error);
                }
            }
            CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
            CompilerParameters parameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true
            };
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Data.dll");
            parameters.ReferencedAssemblies.Add("System.Xml.dll");
            parameters.ReferencedAssemblies.Add("System.Web.Services.dll");
            CompilerResults results = provider.CompileAssemblyFromDom(parameters, generator.TargetCompileUnit);
            if(!results.Errors.HasErrors)
            {
                Assembly assembly = results.CompiledAssembly;
                Type[] types = assembly.GetTypes();
                foreach(Type t in types)
                {
                    if(t.IsClass&&t.IsPublic&&t.Name.EndsWith("Client"))
                    {
                        object Sobj = Activator.CreateInstance(t, new object[] { b, new EndpointAddress(uri.Replace(".?wsdl", "")) });
                        MethodInfo info = t.GetMethod(MethodName);
                        if(info!=null)
                        {
                          T result=(T)info.Invoke(Sobj, para);
                        }
                    }
                }
                TxtLog.Instance.WriteLineToFile("未找到需要调用的类型或者方法!",LogType.Error);
                return default;
            }
            else
            {
                TxtLog.Instance.WriteLineToFile("从{0}获取WSDL后导入元素据成功,但动态编译代码时发生错误,请尝试调用{1}类将代码生成到本地进行查看!!".AddParameters(new object[] {uri,nameof(GetServiceProxyClassFile)}),
                    LogType.Error);
                return default;
            }
        }
        /// <summary>
        /// 动态调用WebService
        /// </summary>
        /// <param name="uri">服务 地址</param>
        /// <param name="MethodName">要调用的方法名称</param>
        /// <param name="para">参数</param>
        /// <returns>返回调用结果</returns>
        public static object DynamicCallService(string uri, string MethodName, params object[] para)
        {
            uri = HandleUrl(uri);
            MetadataExchangeClient client = new MetadataExchangeClient(new Uri(uri), MetadataExchangeClientMode.HttpGet)
            {
                ResolveMetadataReferences = true
            };
            MetadataSet metadata = client.GetMetadata();
            WsdlImporter wsdl = new WsdlImporter(metadata);
            ServiceContractGenerator generator = new ServiceContractGenerator();
            XsdDataContractImporter imp;
            if (!wsdl.State.TryGetValue(typeof(XsdDataContractImporter), out object obj))
            {
                imp = new XsdDataContractImporter
                {
                    Options = new ImportOptions()
                };
                wsdl.State.Add(typeof(XsdDataContractImporter), imp);
            }
            else
            {
                imp = (XsdDataContractImporter)obj;
                if (imp.Options == null)
                {
                    imp.Options = new ImportOptions();
                }
            }
            System.Collections.ObjectModel.Collection<ContractDescription> a = wsdl.ImportAllContracts();
            wsdl.ImportAllEndpoints();
            System.ServiceModel.Channels.Binding b = wsdl.ImportAllBindings()[0];
            foreach (var m in a)
            {
                generator.GenerateServiceContractType(m);
            }
            if (generator.Errors.Count != 0)
            {
                foreach (var l in generator.Errors)
                {
                    TxtLog.Instance.WriteLineToFile("动态调用发生错误:" + l, LogType.Error);
                    return null;
                }
            }
            //动态编译
            CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
            CompilerParameters parameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true
            };
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Data.dll");
            parameters.ReferencedAssemblies.Add("System.Xml.dll");
            parameters.ReferencedAssemblies.Add("System.Web.Services.dll");
            CompilerResults results = provider.CompileAssemblyFromDom(parameters, generator.TargetCompileUnit);
            if (!results.Errors.HasErrors)
            {
                Assembly assembly = results.CompiledAssembly;
                Type[] types = assembly.GetTypes();
                foreach (Type t in types)
                {
                    if (t.IsClass && t.IsPublic && t.Name.EndsWith("Client"))
                    {
                        object Sobj = Activator.CreateInstance(t, new object[] { b, new EndpointAddress(uri.Replace(".?wsdl", "")) });
                        MethodInfo info = t.GetMethod(MethodName);
                        if (info != null)
                        {
                            return info.Invoke(Sobj, para);
                        }
                    }
                }
                TxtLog.Instance.WriteLineToFile("未找到需要调用的类型或者方法!", LogType.Error);
                return null;
            }
            else
            {
                TxtLog.Instance.WriteLineToFile("从{0}获取WSDL后导入元素据成功,但动态编译代码时发生错误,请尝试调用{1}类将代码生成到本地进行查看!!".AddParameters(new object[] { uri, nameof(GetServiceProxyClassFile) }),
                    LogType.Error);
                return null;
            }
        }
        public static Type[] GetAllTypes(string uri)
        {
            uri = HandleUrl(uri);
            MetadataExchangeClient client = new MetadataExchangeClient(new Uri(uri), MetadataExchangeClientMode.HttpGet)
            {
                ResolveMetadataReferences = true
            };
            MetadataSet metadata = client.GetMetadata();
            WsdlImporter wsdl = new WsdlImporter(metadata);
            ServiceContractGenerator generator = new ServiceContractGenerator();
            XsdDataContractImporter imp;
            if (!wsdl.State.TryGetValue(typeof(XsdDataContractImporter), out object obj))
            {
                imp = new XsdDataContractImporter
                {
                    Options = new ImportOptions()
                };
                wsdl.State.Add(typeof(XsdDataContractImporter), imp);
            }
            else
            {
                imp = (XsdDataContractImporter)obj;
                if (imp.Options == null)
                {
                    imp.Options = new ImportOptions();
                }
            }
            System.Collections.ObjectModel.Collection<ContractDescription> a = wsdl.ImportAllContracts();
            wsdl.ImportAllEndpoints();
            wsdl.ImportAllBindings();
            foreach (var m in a)
            {
                generator.GenerateServiceContractType(m);
            }
            if (generator.Errors.Count != 0)
            {
                foreach (var l in generator.Errors)
                {
                    TxtLog.Instance.WriteLineToFile("动态调用发生错误:" + l, LogType.Error);
                    return null;
                }
            }
            CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
            CompilerParameters parameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true
            };
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Data.dll");
            parameters.ReferencedAssemblies.Add("System.Xml.dll");
            parameters.ReferencedAssemblies.Add("System.Web.Services.dll");
            CompilerResults results = provider.CompileAssemblyFromDom(parameters, generator.TargetCompileUnit);
            if (!results.Errors.HasErrors)
            {
                Assembly assembly = results.CompiledAssembly;
                Type[] types = assembly.GetTypes();
                return types;
            }
            return null;
        }
        /// <summary>
        /// 获取动态客户类的所有方法
        /// </summary>
        /// <param name="uri">服务地址</param>
        /// <returns>所有方法信息</returns>
        public static string[] GetAllClientMethod(string uri)
        {
            uri = HandleUrl(uri);
            MetadataExchangeClient client = new MetadataExchangeClient(new Uri(uri), MetadataExchangeClientMode.HttpGet)
            {
                ResolveMetadataReferences = true
            };
            MetadataSet metadata = client.GetMetadata();
            WsdlImporter wsdl = new WsdlImporter(metadata);
            ServiceContractGenerator generator = new ServiceContractGenerator();
            XsdDataContractImporter imp;
            if (!wsdl.State.TryGetValue(typeof(XsdDataContractImporter), out object obj))
            {
                imp = new XsdDataContractImporter
                {
                    Options = new ImportOptions()
                };
                wsdl.State.Add(typeof(XsdDataContractImporter), imp);
            }
            else
            {
                imp = (XsdDataContractImporter)obj;
                if (imp.Options == null)
                {
                    imp.Options = new ImportOptions();
                }
            }
            System.Collections.ObjectModel.Collection<ContractDescription> a = wsdl.ImportAllContracts();
            wsdl.ImportAllEndpoints();
            wsdl.ImportAllBindings();
            foreach (var m in a)
            {
                generator.GenerateServiceContractType(m);
            }
            if (generator.Errors.Count != 0)
            {
                foreach (var l in generator.Errors)
                {
                    TxtLog.Instance.WriteLineToFile("动态调用发生错误:" + l, LogType.Error);
                    return null;
                }
            }
            CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
            CompilerParameters parameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true
            };
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Data.dll");
            parameters.ReferencedAssemblies.Add("System.Xml.dll");
            parameters.ReferencedAssemblies.Add("System.Web.Services.dll");
            CompilerResults results = provider.CompileAssemblyFromDom(parameters, generator.TargetCompileUnit);
            if (!results.Errors.HasErrors)
            {
                Assembly assembly = results.CompiledAssembly;
                Type[] types = assembly.GetTypes();
                foreach (Type t in types)
                {
                    if (t.IsClass && t.IsPublic && t.Name.EndsWith("Client"))
                    {
                        List<string> list = new List<string>();
                        foreach(MethodInfo method in t.GetMethods())
                        {
                            if(method.IsPublic&&method.IsHideBySig&&!method.IsVirtual&&!method.IsStatic&&!method.IsSpecialName)
                            {
                                list.Add(method.Name);
                            }
                        }
                        return list.ToArray();
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// 获取所有参数的类型
        /// </summary>
        /// <param name="uri">服务地址</param>
        /// <param name="MethodName">方法名</param>
        /// <returns></returns>
        public static Dictionary<string,string>GetAllParaTypes(string uri, string MethodName)
        {
            uri = HandleUrl(uri);
            MetadataExchangeClient client = new MetadataExchangeClient(new Uri(uri), MetadataExchangeClientMode.HttpGet)
            {
                ResolveMetadataReferences = true
            };
            MetadataSet metadata = client.GetMetadata();
            WsdlImporter wsdl = new WsdlImporter(metadata);
            ServiceContractGenerator generator = new ServiceContractGenerator();
            XsdDataContractImporter imp;
            if (!wsdl.State.TryGetValue(typeof(XsdDataContractImporter), out object obj))
            {
                imp = new XsdDataContractImporter
                {
                    Options = new ImportOptions()
                };
                wsdl.State.Add(typeof(XsdDataContractImporter), imp);
            }
            else
            {
                imp = (XsdDataContractImporter)obj;
                if (imp.Options == null)
                {
                    imp.Options = new ImportOptions();
                }
            }
            System.Collections.ObjectModel.Collection<ContractDescription> a = wsdl.ImportAllContracts();
            wsdl.ImportAllEndpoints();
            wsdl.ImportAllBindings();
            foreach (var m in a)
            {
                generator.GenerateServiceContractType(m);
            }
            if (generator.Errors.Count != 0)
            {
                foreach (var l in generator.Errors)
                {
                    TxtLog.Instance.WriteLineToFile("动态调用发生错误:" + l, LogType.Error);
                    return null;
                }
            }
            CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
            CompilerParameters parameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true
            };
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Data.dll");
            parameters.ReferencedAssemblies.Add("System.Xml.dll");
            parameters.ReferencedAssemblies.Add("System.Web.Services.dll");
            CompilerResults results = provider.CompileAssemblyFromDom(parameters, generator.TargetCompileUnit);
            if (!results.Errors.HasErrors)
            {
                Assembly assembly = results.CompiledAssembly;
                Type[] types = assembly.GetTypes();
                foreach (Type t in types)
                {
                    if (t.IsClass && t.IsPublic && t.Name.EndsWith("Client"))
                    {
                        MethodInfo info = t.GetMethod(MethodName);
                        ParameterInfo[] para = info.GetParameters();
                        Dictionary<string, string> list = new Dictionary<string, string>();
                        foreach(var m in para)
                        {
                            list.Add(m.Name, m.ParameterType.FullName);
                        }
                        return list;
                    }
                }
                return null;
            }
            return null;
        }
    }
}

 

posted @ 2019-05-08 20:01  淺笑嫣然  阅读(32)  评论(0)    收藏  举报