2

WSDL を介して ASMX Web サービスを反映する必要があります。thisの受け入れられた答えを使用して、単純なケースはすべてうまくいきます。しかし、そこにはいくつかの複雑な型 (厳密に型指定されたデータセット) が定義されています。サービスの元のソースは次のようになります

[WebMethod]
public int GetCustomer(string civicRegistrationNo, out MyCompany.E_WebServices.DataSets.CustomerDataSet customerDS)

リフレクションではメソッドが次のようになるため、これCustomerDataSetは私に問題を引き起こします

GetCustomer [Int32]: civicRegistrationNo [String], customerDS [out XmlElement]

一方、私が見たいのは(そしてDLLを直接反映すると何が出るか)です

GetCustomer [Int32]: civicRegistrationNo [String], customerDS [out CustomerDataSet]

CustomerDataSetタイプを正しく取得するためにコード(以下)をどのように改善すればよいXmlElementですか? 確かに、WSDL のこのブロックと関係があります。

<s:import namespace="http://tempuri.org/CustomerDataSet.xsd"/>
<s:import schemaLocation="http://localhost/E-WebServices/WSCustomer.asmx?schema=CustomerDataSet" namespace="http://tempuri.org/CustomerDataSet.xsd"/>

はい、開くとブラウザでその定義を見ることができます

http://localhost/E-WebServices/WSCustomer.asmx?schema=CustomerDataSet

しかし、以下のコードからそれを取得するにはどうすればよいでしょうか?

var client = new System.Net.WebClient();
var stream = client.OpenRead("http://localhost/E-WebServices/WSCustomer.asmx?wsdl");
var description = ServiceDescription.Read(stream);
var importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap12";
importer.AddServiceDescription(description, null, null);
importer.Style = ServiceDescriptionImportStyle.Client;
importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
var nmspace = new CodeNamespace();
var unit1 = new CodeCompileUnit();
unit1.Namespaces.Add(nmspace);
var warning = importer.Import(nmspace, unit1);
if (warning == 0)
{
    CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
    string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };
    CompilerParameters parms = new CompilerParameters(assemblyReferences);
    CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
    if (results.Errors.Count > 0)
    {
        foreach (CompilerError oops in results.Errors)
            Debug.WriteLine(oops.ErrorText);
        throw new Exception("Compile Error Occured calling webservice");
    }
    object service = results.CompiledAssembly.CreateInstance("WSCustomer");
    List<MethodInfo> methods = service.GetType().GetMethods().ToList();
    // use them somehow
}

私は、Visual Studio 自体が何をしているのかに少し触発されています。Web ref が追加された場合、WSDL しかありません (同じマシンにある場合でも、その DLL に直接移動しないと思います)。うまく含まれているタイプ。だから私はそれが可能でなければならないと思います!? ここに画像の説明を入力

4

1 に答える 1

1

OK、うまくいったようです(おそらく最もクリーンな方法ではありません)

string serviceUrl = "http://localhost/E-WebServices/WSCustomer.asmx";
var client = new WebClient();
ServiceDescription descr;
using (var stream = client.OpenRead(serviceUrl + "?wsdl"))
{
    descr = ServiceDescription.Read(stream);
}
var importer = new ServiceDescriptionImporter()
{
    ProtocolName = "Soap12",
    Style = ServiceDescriptionImportStyle.Client,
    CodeGenerationOptions = CodeGenerationOptions.GenerateProperties,
};
importer.AddServiceDescription(descr, null, null);
// Add any imported schemas
var importedSchemas = new List<string>();
foreach (XmlSchema wsdlSchema in descr.Types.Schemas)
{
    foreach (XmlSchemaObject externalSchema in wsdlSchema.Includes)
    {
        if (externalSchema is XmlSchemaImport)
        {
            XmlSchemaImport schemaImport = externalSchema as XmlSchemaImport;
            var split = schemaImport.Namespace.Split(new char[] { '/', '.' });
            string schemaId = split[split.Count() - 2];
            if (importedSchemas.Contains(schemaId))
                continue;
            importedSchemas.Add(schemaId);
            Uri schemaUri = new Uri(serviceUrl + "?schema=" + schemaId);
            XmlSchema schema;
            using (var wsdlStream = client.OpenRead(schemaUri))
            {
                schema = XmlSchema.Read(wsdlStream, null);
            }
            importer.Schemas.Add(schema);
        }
    }
}
var nmspace = new CodeNamespace();
var unit1 = new CodeCompileUnit();
unit1.Namespaces.Add(nmspace);
var warning = importer.Import(nmspace, unit1);
if (warning == 0)
{
    CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
    string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };
    CompilerParameters parms = new CompilerParameters(assemblyReferences);
    CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
    if (results.Errors.Count > 0)
    {
        foreach (CompilerError oops in results.Errors)
            Debug.WriteLine(oops.ErrorText);
        throw new Exception("Compile Error Occured calling webservice");
    }
    object service = results.CompiledAssembly.CreateInstance("WSCustomer");
    Type t = service.GetType();
    List<MethodInfo> methods = t.GetMethods().ToList();
    // use them somehow
}
于 2013-01-29T09:29:25.380 に答える