通过反射在 WCF 中设置超时
Set Timeout in WCF via Reflection
我在使用 WCF 时需要设置超时。
异常: 'System.NullReferenceException' 类型的异常,变量 属性Info 为空。我无法获得代理类型的 属性 超时。
我有下面的代码,我在设置值时出错。 (我硬编码了“1000”)
private object GetWCFInstance(ref CompilerResults compilerResults, string WCFAddress, string contractName)
{
object proxyInstance = null;
// Define the WSDL Get address, contract name and parameters, with this we can extract WSDL details any time
Uri address = new Uri(WCFAddress);
// For HttpGet endpoints use a Service WSDL address a mexMode of .HttpGet and for MEX endpoints use a MEX address and a mexMode of .MetadataExchange
MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet;
//string contractName = "IService1";
// Get the metadata file from the service.
MetadataExchangeClient metadataExchangeClient = new MetadataExchangeClient(address, mexMode);
metadataExchangeClient.ResolveMetadataReferences = true;
//One can also provide credentials if service needs that by the help following two lines.
//ICredentials networkCredential = new NetworkCredential("", "", "");
//metadataExchangeClient.HttpCredentials = networkCredential;
//Gets the meta data information of the service.
MetadataSet metadataSet = metadataExchangeClient.GetMetadata();
// Import all contracts and endpoints.
WsdlImporter wsdlImporter = new WsdlImporter(metadataSet);
//Import all contracts.
Collection<ContractDescription> contracts = wsdlImporter.ImportAllContracts();
//Import all end points.
ServiceEndpointCollection allEndpoints = wsdlImporter.ImportAllEndpoints();
// Generate type information for each contract.
ServiceContractGenerator serviceContractGenerator = new ServiceContractGenerator();
//Dictinary has been defined to keep all the contract endpoints present, contract name is key of the dictionary item.
var endpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>();
foreach (ContractDescription contract in contracts)
{
serviceContractGenerator.GenerateServiceContractType(contract);
// Keep a list of each contract's endpoints.
endpointsForContracts[contract.Name] = allEndpoints.Where(ep => ep.Contract.Name == contract.Name).ToList();
}
// Generate a code file for the contracts.
CodeGeneratorOptions codeGeneratorOptions = new CodeGeneratorOptions();
codeGeneratorOptions.BracingStyle = "C";
// Create Compiler instance of a specified language.
CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");
// Adding WCF-related assemblies references as copiler parameters, so as to do the compilation of particular service contract.
CompilerParameters compilerParameters = new CompilerParameters(new string[] { "System.dll", "System.ServiceModel.dll", "System.Runtime.Serialization.dll" });
compilerParameters.GenerateInMemory = true;
//Gets the compiled assembly.
compilerResults = codeDomProvider.CompileAssemblyFromDom(compilerParameters, serviceContractGenerator.TargetCompileUnit);
if (compilerResults.Errors.Count <= 0)
{
// Find the proxy type that was generated for the specified contract (identified by a class that implements the contract and ICommunicationbject - this is contract
//implemented by all the communication oriented objects).
Type proxyType = compilerResults.CompiledAssembly.GetTypes().First(t => t.IsClass && t.GetInterface(contractName) != null &&
t.GetInterface(typeof(ICommunicationObject).Name) != null);
// Now we get the first service endpoint for the particular contract.
ServiceEndpoint serviceEndpoint = endpointsForContracts[contractName].First();
// Create an instance of the proxy by passing the endpoint binding and address as parameters.
proxyInstance = compilerResults.CompiledAssembly.CreateInstance(proxyType.Name, false, System.Reflection.BindingFlags.CreateInstance, null,
new object[] { serviceEndpoint.Binding, serviceEndpoint.Address }, System.Globalization.CultureInfo.CurrentCulture, null);
System.Reflection.PropertyInfo propertyInfo = proxyType.GetProperty("Timeout");
**propertyInfo.SetValue(proxyInstance, 1000, null);**
object check = propertyInfo.GetValue(proxyInstance, null);
}
return proxyInstance;
}
谢谢
我终于解决了这个问题,我不需要 app.config 中的任何东西,wef.config 配置了相同的代码并将这些行放在客户端中。
我只需要转换 ChannelFactory,然后转换 BasicHttpBinding 并设置参数。
谢谢大家
var timeOut=new TimeSpan(0, 10, 0);
int timeOutInt = 2147483647;
PropertyInfo channelFactoryProperty = proxyInstance.GetType().GetProperty("ChannelFactory");
if (channelFactoryProperty == null)
{
throw new InvalidOperationException("There is no ''ChannelFactory'' property on the DomainClient.");
}
ChannelFactory factory = (ChannelFactory)channelFactoryProperty.GetValue(proxyInstance, null);
factory.Endpoint.Binding.SendTimeout = timeOut;
factory.Endpoint.Binding.OpenTimeout = timeOut;
factory.Endpoint.Binding.ReceiveTimeout = timeOut;
factory.Endpoint.Binding.CloseTimeout = timeOut;
BasicHttpBinding _binding = (BasicHttpBinding)factory.Endpoint.Binding;
_binding.MaxBufferPoolSize = timeOutInt;
_binding.MaxBufferSize = timeOutInt;
_binding.MaxReceivedMessageSize = timeOutInt;
_binding.OpenTimeout = timeOut;
我在使用 WCF 时需要设置超时。
异常: 'System.NullReferenceException' 类型的异常,变量 属性Info 为空。我无法获得代理类型的 属性 超时。
我有下面的代码,我在设置值时出错。 (我硬编码了“1000”)
private object GetWCFInstance(ref CompilerResults compilerResults, string WCFAddress, string contractName)
{
object proxyInstance = null;
// Define the WSDL Get address, contract name and parameters, with this we can extract WSDL details any time
Uri address = new Uri(WCFAddress);
// For HttpGet endpoints use a Service WSDL address a mexMode of .HttpGet and for MEX endpoints use a MEX address and a mexMode of .MetadataExchange
MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.HttpGet;
//string contractName = "IService1";
// Get the metadata file from the service.
MetadataExchangeClient metadataExchangeClient = new MetadataExchangeClient(address, mexMode);
metadataExchangeClient.ResolveMetadataReferences = true;
//One can also provide credentials if service needs that by the help following two lines.
//ICredentials networkCredential = new NetworkCredential("", "", "");
//metadataExchangeClient.HttpCredentials = networkCredential;
//Gets the meta data information of the service.
MetadataSet metadataSet = metadataExchangeClient.GetMetadata();
// Import all contracts and endpoints.
WsdlImporter wsdlImporter = new WsdlImporter(metadataSet);
//Import all contracts.
Collection<ContractDescription> contracts = wsdlImporter.ImportAllContracts();
//Import all end points.
ServiceEndpointCollection allEndpoints = wsdlImporter.ImportAllEndpoints();
// Generate type information for each contract.
ServiceContractGenerator serviceContractGenerator = new ServiceContractGenerator();
//Dictinary has been defined to keep all the contract endpoints present, contract name is key of the dictionary item.
var endpointsForContracts = new Dictionary<string, IEnumerable<ServiceEndpoint>>();
foreach (ContractDescription contract in contracts)
{
serviceContractGenerator.GenerateServiceContractType(contract);
// Keep a list of each contract's endpoints.
endpointsForContracts[contract.Name] = allEndpoints.Where(ep => ep.Contract.Name == contract.Name).ToList();
}
// Generate a code file for the contracts.
CodeGeneratorOptions codeGeneratorOptions = new CodeGeneratorOptions();
codeGeneratorOptions.BracingStyle = "C";
// Create Compiler instance of a specified language.
CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");
// Adding WCF-related assemblies references as copiler parameters, so as to do the compilation of particular service contract.
CompilerParameters compilerParameters = new CompilerParameters(new string[] { "System.dll", "System.ServiceModel.dll", "System.Runtime.Serialization.dll" });
compilerParameters.GenerateInMemory = true;
//Gets the compiled assembly.
compilerResults = codeDomProvider.CompileAssemblyFromDom(compilerParameters, serviceContractGenerator.TargetCompileUnit);
if (compilerResults.Errors.Count <= 0)
{
// Find the proxy type that was generated for the specified contract (identified by a class that implements the contract and ICommunicationbject - this is contract
//implemented by all the communication oriented objects).
Type proxyType = compilerResults.CompiledAssembly.GetTypes().First(t => t.IsClass && t.GetInterface(contractName) != null &&
t.GetInterface(typeof(ICommunicationObject).Name) != null);
// Now we get the first service endpoint for the particular contract.
ServiceEndpoint serviceEndpoint = endpointsForContracts[contractName].First();
// Create an instance of the proxy by passing the endpoint binding and address as parameters.
proxyInstance = compilerResults.CompiledAssembly.CreateInstance(proxyType.Name, false, System.Reflection.BindingFlags.CreateInstance, null,
new object[] { serviceEndpoint.Binding, serviceEndpoint.Address }, System.Globalization.CultureInfo.CurrentCulture, null);
System.Reflection.PropertyInfo propertyInfo = proxyType.GetProperty("Timeout");
**propertyInfo.SetValue(proxyInstance, 1000, null);**
object check = propertyInfo.GetValue(proxyInstance, null);
}
return proxyInstance;
}
谢谢
我终于解决了这个问题,我不需要 app.config 中的任何东西,wef.config 配置了相同的代码并将这些行放在客户端中。
我只需要转换 ChannelFactory,然后转换 BasicHttpBinding 并设置参数。
谢谢大家
var timeOut=new TimeSpan(0, 10, 0);
int timeOutInt = 2147483647;
PropertyInfo channelFactoryProperty = proxyInstance.GetType().GetProperty("ChannelFactory");
if (channelFactoryProperty == null)
{
throw new InvalidOperationException("There is no ''ChannelFactory'' property on the DomainClient.");
}
ChannelFactory factory = (ChannelFactory)channelFactoryProperty.GetValue(proxyInstance, null);
factory.Endpoint.Binding.SendTimeout = timeOut;
factory.Endpoint.Binding.OpenTimeout = timeOut;
factory.Endpoint.Binding.ReceiveTimeout = timeOut;
factory.Endpoint.Binding.CloseTimeout = timeOut;
BasicHttpBinding _binding = (BasicHttpBinding)factory.Endpoint.Binding;
_binding.MaxBufferPoolSize = timeOutInt;
_binding.MaxBufferSize = timeOutInt;
_binding.MaxReceivedMessageSize = timeOutInt;
_binding.OpenTimeout = timeOut;