我有 WCF 服务端点;我无权访问该服务的接口(即合同)。我有需要调用的 EndPoint 详细信息和 MethodName。
我如何在 C# 中做到这一点;我正在使用 netTcpBinding ...
提前致谢
海洋
我有 WCF 服务端点;我无权访问该服务的接口(即合同)。我有需要调用的 EndPoint 详细信息和 MethodName。
我如何在 C# 中做到这一点;我正在使用 netTcpBinding ...
提前致谢
海洋
不确定这是否正是您想要的,但您可以使用 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 参数。此外,以上假设您调用的方法只接受一个参数,即 DataContract 对象。
希望这能让你走上正确的轨道,如果你仍然需要它。