Ejemplo n.º 1
0
        /// <summary>
        /// 增加程序集路径和端口类,并序列化到XML文件
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="portType"></param>
        public static void Add(String assemblyPath, String portType)
        {
            AssemblyType assType = GetInstance(assemblyPath);

            if (assType == null)
            {
                //s_lstAssemblyType.Add(new AssemblyType(assemblyPath, portType));
                s_dictAssemblyType[assemblyPath] = new AssemblyType(assemblyPath, portType);
            }
            else
            {
                assType.PortType = portType;
            }

            s_needWriteToDisk = true; // 表示需要序列化到磁盘上
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 编译程序集
        /// </summary>
        /// <param name="url"></param>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        private static String CompilerAssembly(String url, String serviceName, String assemblyPath)
        {
            // 1. 使用 WebClient 下载 WSDL 信息。
            WebClient web = new WebClient();

            using (Stream stream = web.OpenRead(url + "?WSDL"))
            {
                // 2. 创建和格式化 WSDL 文档。
                ServiceDescription description = ServiceDescription.Read(stream);

                // 3. 创建客户端代理代理类。
                ServiceDescriptionImporter importer = new ServiceDescriptionImporter();

                importer.ProtocolName          = "Soap";                               // 指定访问协议。
                importer.Style                 = ServiceDescriptionImportStyle.Client; // 生成客户端代理。
                importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;

                importer.AddServiceDescription(description, null, null); // 添加 WSDL 文档。

                // 4. 使用 CodeDom 编译客户端代理类。
                CodeNamespace   nmspace = new CodeNamespace(serviceName); // 为代理类添加命名空间,缺省为全局空间。
                CodeCompileUnit unit    = new CodeCompileUnit();
                unit.Namespaces.Add(nmspace);

                ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
                CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

                // 4.1 根据ESB的需要修正自动生成的代码, 只针对Java进行修正
                if (!url.EndsWith(".asmx"))
                {
                    FixAutoGenCode(nmspace, description);
                }

                CompilerParameters parameter = new CompilerParameters();
                parameter.GenerateExecutable = false;
                parameter.GenerateInMemory   = false;
                parameter.OutputAssembly     = assemblyPath; // 可以指定你所需的任何文件名。
                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);

                // 5. 如果编译出现异常,则直接抛出
                if (result.Errors.HasErrors)
                {
                    System.Text.StringBuilder sb = new StringBuilder();
                    sb.AppendLine("编译代理程序集出现异常:");

                    foreach (CompilerError ce in result.Errors)
                    {
                        sb.Append(ce.ToString() + System.Environment.NewLine);
                    }
                    throw new Exception(sb.ToString());
                }

                // 6. 返回代理类的名词
                Regex regSoap = new Regex("Soap$");
                // 注意:此处要用全名,因为可能存在多个服务共用一个DLL的情况
                String portTypeFullName = serviceName + "." + regSoap.Replace(description.PortTypes[0].Name, "");

                //--记录代理程序集的端口类名,当不需要编译程序集的时候可以直接从AssemblyType.GetInstance(assemblyPath).PortType获取
                AssemblyType.Add(assemblyPath, portTypeFullName);

                return(portTypeFullName);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 加载代理程序集
        /// </summary>
        /// <param name="url"></param>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        private static SoapClientItem LoadAssembly(String url, String serviceName)
        {
            String assemblyPath     = GetAssemblyPath(url);
            String portTypeFullName = String.Empty; // 注意此处要用全名:命名空间.类名

            // 如果代理程序集不存在则编译生成代理程序集,否则直接加载
            if (!File.Exists(assemblyPath))
            {
                portTypeFullName = CompilerAssembly(url, serviceName, assemblyPath);
            }
            else
            {
                portTypeFullName = AssemblyType.GetInstance(assemblyPath).PortType;
            }

            // 如果没有获取到端口类型则清空程序集缓存并抛出异常
            if (portTypeFullName == String.Empty)
            {
                ClearCache(url);
                throw new Exception(String.Format("获取服务:{0}『{1}』的端口类型失败!", serviceName, url));
            }

            Assembly asm = null;

            using (FileStream fs = File.OpenRead(assemblyPath))
            {
                asm = Assembly.Load(fs.ReadBytes(fs.Length)); // 此处采用文件流进行加载,使得加载后的程序集仍然可以被重新编译
            }

            if (asm == null)
            {
                throw new Exception(String.Format("加载代理程序集{0}失败!", assemblyPath));
            }

            //Assembly asm = result.CompiledAssembly;
            //Type portType = asm.GetType(String.Format("{0}.{1}", serviceName, portTypeName));
            //Type reqType = asm.GetType(String.Format("{0}.request", serviceName));

            // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。
            Type portType = GetTypeFromAssembly(asm, portTypeFullName, assemblyPath);
            Type reqType  = GetTypeFromAssembly(asm, String.Format("{0}.request", portTypeFullName.Split('.')[0]), assemblyPath);

            // 创建端口类对象
            Object port = Activator.CreateInstance(portType);

            if (port == null)
            {
                throw new Exception(String.Format("创建:{0}『{1}』的端口类型对象失败!", serviceName, url));
            }

            // 将超时设置为10分钟
            portType.InvokeMember("Timeout", BindingFlags.SetProperty, null, port, new Object[] { 10 * 60 * 1000 });

            SoapClientItem item = new SoapClientItem()
            {
                ProxyAssembly = asm,
                PortObject    = port,
                PortType      = portType,
                RequestType   = reqType
            };

            return(item);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 增加程序集路径和端口类,并序列化到XML文件
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="portType"></param>
        public static void Add(String assemblyPath, String portType)
        {
            AssemblyType assType = GetInstance(assemblyPath);
            if (assType == null)
            {
                //s_lstAssemblyType.Add(new AssemblyType(assemblyPath, portType));
                s_dictAssemblyType[assemblyPath] = new AssemblyType(assemblyPath, portType);
            }
            else
            {
                assType.PortType = portType;
            }

            s_needWriteToDisk = true; // 表示需要序列化到磁盘上
        }