2

WCF サービス エンドポイントがあります。そのサービスのインターフェイス (契約) にアクセスできません。呼び出す必要がある EndPoint の詳細と MethodName があります。

C# でこれを行うにはどうすればよいですか。私はnetTcpBindingを使用しています...

前もって感謝します

海洋

4

1 に答える 1

3

これがまさにあなたが望むものかどうかはわかりませんが、WsdlImporter を使用して WSDL にアクセスし、メタデータ (DataContracts や OperationContracts など) を取得できます。例えば:

        MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet;

        // Get Metadata file from service
        MetadataExchangeClient mexClient = new MetadataExchangeClient(mexAddress, mexMode);
        mexClient.ResolveMetadataReferences = true;
        MetadataSet metaSet = mexClient.GetMetadata(mexAddress, mexMode);

        //Import all contracts and endpoints
        WsdlImporter importer = new WsdlImporter(metaSet);
        var contracts = importer.ImportAllContracts();
        ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints();

        //Generate type information for each contract
        ServiceContractGenerator generator = new ServiceContractGenerator();
        this.EndpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>();

        foreach (ContractDescription contract in contracts)
        {
            generator.GenerateServiceContractType(contract);
            // Inspect if the name matches one you're looking for, or do whatever
            //  else you might need
        }

次に、コードをメモリに動的にコンパイルできます。

// Generate a code file for the contracts 
        CodeGeneratorOptions options = new CodeGeneratorOptions();
        options.BracingStyle = "C";
        CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");

        // Compile the code file to an in-memory assembly
        // Don't forget to add all WCF-related assemblies as references
        CompilerParameters compilerParameters = new CompilerParameters(
            new string[] { 
                "System.dll", "System.ServiceModel.dll", 
                "System.Runtime.Serialization.dll" });
        compilerParameters.GenerateInMemory = true;

        CompilerResults results = codeDomProvider.CompileAssemblyFromDom(compilerParameters, generator.TargetCompileUnit);

最後に、それに応じてメソッドを実行できます。

Type clientProxyType = this.Cr.CompiledAssembly.GetTypes().First(t => t.IsClass && t.GetInterface(listServiceContracts.SelectedValue) != null && t.GetInterface(typeof(ICommunicationObject).Name) != null);
object dataContract = this.Cr.CompiledAssembly.CreateInstance(dataContractType.FullName, false, System.Reflection.BindingFlags.CreateInstance, null, null, CultureInfo.CurrentCulture, null);

// set the dataContract properties however they need to be set

// Get the first service endpoint for the contract
        ServiceEndpoint serviceEndPoint = this.EndpointsForContracts[listServiceContracts.SelectedValue].First();

        object clientProxyInstance = this.Cr.CompiledAssembly.CreateInstance(clientProxyType.Name, false, System.Reflection.BindingFlags.CreateInstance, null, new object[] { serviceEndPoint.Binding, serviceEndPoint.Address }, CultureInfo.CurrentCulture, null);

        Type myType = clientProxyInstance.GetType();
        object[] arg = { dataContract };

        // Now call the remote procedure via SOAP, get back response
        var returnVal = myType.InvokeMember("OPERATION YOU WANT TO EXECUTE", BindingFlags.InvokeMethod, null, clientProxyInstance, arg);

繰り返しますが、これはあなたがしようとしていることには完璧ではないかもしれません。また、あなたの投稿はかなり前のことなので、これは古いニュースかもしれません。しかし、念のため... うまくいけば、これは役に立ちます。DataContract 引数を適切に設定する方法を決定するために、返される型を検査する必要がある可能性があります。また、上記では、呼び出しているメソッドが 1 つの引数 (DataContract オブジェクト) のみを受け取ることを前提としています。

それでも必要な場合は、これが正しい軌道に乗ることを願っています。

于 2014-06-30T20:01:39.280 に答える