이전에 작동하지 못했던 on-the-fly 생성 어셈블리를 사용하여 솔루션을 찾았습니다. 출발 지점은 http://refact.blogspot.com/2007_05_01_archive.html입니다.
예. 내가 명시 적으로 methods[0]
및 methods[1]
를 사용하지만 실제로이 코스의 메소드 이름을 확인 할이 코드에서
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.Web.Services;
using System.Web.Services.Description;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Xml.Serialization;
using System.IO;
using System.Reflection;
namespace GenericSoapClient
{
class Program
{
static void method1()
{
Uri uri = new Uri("http://www.webservicex.net/periodictable.asmx?WSDL");
WebRequest webRequest = WebRequest.Create(uri);
System.IO.Stream requestStream = webRequest.GetResponse().GetResponseStream();
// Get a WSDL
ServiceDescription sd = ServiceDescription.Read(requestStream);
string sdName = sd.Services[0].Name;
// Initialize a service description servImport
ServiceDescriptionImporter servImport = new ServiceDescriptionImporter();
servImport.AddServiceDescription(sd, String.Empty, String.Empty);
servImport.ProtocolName = "Soap";
servImport.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
CodeNamespace nameSpace = new CodeNamespace();
CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
codeCompileUnit.Namespaces.Add(nameSpace);
// Set Warnings
ServiceDescriptionImportWarnings warnings = servImport.Import(nameSpace, codeCompileUnit);
if (warnings == 0)
{
StringWriter stringWriter =
new StringWriter(System.Globalization.CultureInfo.CurrentCulture);
Microsoft.CSharp.CSharpCodeProvider prov =
new Microsoft.CSharp.CSharpCodeProvider();
prov.GenerateCodeFromNamespace(nameSpace,
stringWriter,
new CodeGeneratorOptions());
string[] assemblyReferences =
new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
CompilerParameters param = new CompilerParameters(assemblyReferences);
param.GenerateExecutable = false;
param.GenerateInMemory = true;
param.TreatWarningsAsErrors = false;
param.WarningLevel = 4;
CompilerResults results = new CompilerResults(new TempFileCollection());
results = prov.CompileAssemblyFromDom(param, codeCompileUnit);
Assembly assembly = results.CompiledAssembly;
Type service = assembly.GetType(sdName);
//MethodInfo[] methodInfo = service.GetMethods();
List<string> methods = new List<string>();
// only find methods of this object type (the one we generated)
// we don't want inherited members (this type inherited from SoapHttpClientProtocol)
foreach (MethodInfo minfo in service.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
methods.Add(minfo.Name);
Console.WriteLine (minfo.Name + " returns " + minfo.ReturnType.ToString());
ParameterInfo[] parameters = minfo.GetParameters();
foreach (ParameterInfo pinfo in parameters)
{
Console.WriteLine(" " + pinfo.Name + " " + pinfo.ParameterType.ToString());
}
}
// Create instance of created web service client proxy
object obj = assembly.CreateInstance(sdName);
Type type = obj.GetType();
object[] args0 = new object[] { };
string result0 = (string)type.InvokeMember(methods[0], BindingFlags.InvokeMethod, null, obj, args0);
Console.WriteLine(result0);
object[] args1 = new object[] { "Oxygen" };
string result1 = (string)type.InvokeMember(methods[1], BindingFlags.InvokeMethod, null, obj, args1);
Console.WriteLine(result1);
}
}
}
}
:이 주기율표 웹 서비스를 사용하는 코드입니다. 이 예제에서는 주기율표의 모든 원소의 이름을 얻은 다음 산소의 원자량을 구합니다.
이 예에는 아직 프록시를 지원하는 논리가 포함되어 있지 않습니다. 나는 여전히 이것을 추가 할 필요가 있지만, 현재로서는 가장 큰 문제, 즉 일반적인 SOAP 클라이언트를 가지고있다.
편집 :
이 코드는 C#을 내가 원래 C++ 솔루션을 요구하고 알고 있지만,이 코드는 아직도 제한된 지역에서 사용할 수있는 (.NET 환경에서 작업 할 수 있음을 증명 내 응용 프로그램의), 그리고 아마도이 코드를 C++/.NET으로 다시 작성하여 내 문제를 해결할 것입니다.
좋은 지적입니다! C++ Builder 환경으로 포팅 될 수 있다고 생각하십니까? 또는 .NET과 Reflection에 종속적입니까? – bluish
@blueish, 이것은 .Net에 실제로 의존합니다. 이 코드는 .Net을 사용하여 클라이언트 클래스를 생성 한 다음 .Net C# 컴파일러를 사용하여 컴파일하고 .Net reflection을 사용하여 클래스를 호출합니다. – Patrick
비록 OP의 문제가 해결되어서 기쁩니다 만,이 질문에 대한 대답은 C#에서와 같이 C#에서 특히 그렇듯이이 대답은 받아 들여지지 않을 수도 있습니다. – zgyarmati