c# – 使用反射动态调用WCF服务
发布时间:2020-12-15 22:07:55 所属栏目:百科 来源:网络整理
导读:我在使用反射调用时将泛型集合传递给WCF服务方法时遇到问题.具体而言,该集合的类型为List KeyValuePair string,string. 我的目标是能够在运行时动态执行WCF服务的方法,而无需在我的客户端应用程序中添加任何对服务的引用.用户应该能够在运行时添加服务,应用
我在使用反射调用时将泛型集合传递给WCF服务方法时遇到问题.具体而言,该集合的类型为List< KeyValuePair< string,string>>.
我的目标是能够在运行时动态执行WCF服务的方法,而无需在我的客户端应用程序中添加任何对服务的引用.用户应该能够在运行时添加服务,应用程序应该能够神奇地处理它. 服务接口 [ServiceContract] public interface ITestService { [OperationContract] string ProcessSimpleType(string value); [OperationContract] string ProcessGenericCollection(List<KeyValuePair<string,string>> genericCol); } 服务实施 public class TestService : ITestService { public string ProcessSimpleType(string value) { return value; } public string ProcessGenericCollection(List<KeyValuePair<string,string>> genericCol) { return "Hello World!"; } } 客户代码 try { Uri mexAddress = new Uri("http://localhost:8732/TestService/?wsdl"); MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet; string contractName = "ITestService"; string operationName = "ProcessGenericCollection"; List<KeyValuePair<string,string>> list = new List<KeyValuePair<string,string>>(); list.Add(new KeyValuePair<string,string>("key","value")); object[] operationParameters = new object[] { list }; MetadataExchangeClient mexClient = new MetadataExchangeClient(mexAddress,mexMode); mexClient.ResolveMetadataReferences = true; MetadataSet metaSet = mexClient.GetMetadata(); WsdlImporter importer = new WsdlImporter(metaSet); Collection<ContractDescription> contracts = importer.ImportAllContracts(); ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints(); ServiceContractGenerator generator = new ServiceContractGenerator(); var endpointsForContracts = new Dictionary<string,IEnumerable<ServiceEndpoint>>(); foreach (ContractDescription contract in contracts) { generator.GenerateServiceContractType(contract); endpointsForContracts[contract.Name] = allEndpoints.Where( se => se.Contract.Name == contract.Name).ToList(); } if (generator.Errors.Count != 0) throw new Exception("There were errors during code compilation."); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BracingStyle = "C"; CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#"); 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); if (results.Errors.Count > 0) { throw new Exception("There were errors during generated code compilation"); } else { Type clientProxyType = results.CompiledAssembly.GetTypes().First( t => t.IsClass && t.GetInterface(contractName) != null && t.GetInterface(typeof(ICommunicationObject).Name) != null); ServiceEndpoint se = endpointsForContracts[contractName].First(); object instance = results.CompiledAssembly.CreateInstance( clientProxyType.Name,false,System.Reflection.BindingFlags.CreateInstance,null,new object[] { se.Binding,se.Address },CultureInfo.CurrentCulture,null); var methodInfo = instance.GetType().GetMethod(operationName); //Invoking the ProcessGenericCollection via reflection will throw an exception object retVal = methodInfo.Invoke(instance,BindingFlags.InvokeMethod,operationParameters,null); Console.WriteLine(retVal.ToString()); } } catch (Exception ex) { Console.WriteLine(ex.Message); } 抛出的错误是:
请记住,在对ProcessSimpleType(…)方法进行测试并传入一个简单类型时,这非常有效.我的问题只有ProcessGenericCollection(…).有没有人遇到过这个问题,如果有的话,你是怎么克服它的? 解决方法
感谢一位同事提供解决方案.对于那些有类似问题的人,我插入了以下内容:
... ... WsdlImporter importer = new WsdlImporter(metaSet); //BEGIN INSERT XsdDataContractImporter xsd = new XsdDataContractImporter(); xsd.Options = new ImportOptions(); xsd.Options.ImportXmlType = true; xsd.Options.GenerateSerializable = true; xsd.Options.ReferencedTypes.Add(typeof(KeyValuePair<string,string>)); xsd.Options.ReferencedTypes.Add(typeof(System.Collections.Generic.List<KeyValuePair<string,string>>)); importer.State.Add(typeof(XsdDataContractImporter),xsd); //END INSERT Collection<ContractDescription> contracts = importer.ImportAllContracts(); ... ... (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |