2013-07-24 2 views
1

가 발생합니다 -이 할 그러나 때마다 :ServiceModel.Discovery.DiscoveryClient (문자열 endpointConfigurationName는) 내가 응용 프로그램 구성 파일을 통해 서비스 검색에 대해 구성하기 위해 노력하고있어 작은 WCF 클라이언트이 경우 ArgumentNullException

// Create a new DiscoveryClient instance from the 'DiscoveryEndpoint' 
// configuration in App.config 
DiscoveryClient discoveryClient = new DiscoveryClient("DiscoveryEndpoint"); 

I을 ArgumentNullException, Value cannot be null. Parameter name: contract을 얻으십시오. DiscoveryClient 생성자의 오버로드에 대해 contract 매개 변수가없고 계약이 App.config (아래 참조)에 올바르게 지정되어 있습니다.

<system.serviceModel> 
    <client> 
    <endpoint name="DiscoveryEndpoint" 
       contract="IExampleContract" 
       kind="dynamicEndpoint" 
       endpointConfiguration="DynamicEndpointConfiguration"/> 
    </client> 

    <standardEndpoints> 
    <dynamicEndpoint> 
     <standardEndpoint name="DynamicEndpointConfiguration"> 
     <discoveryClientSettings> 
      <endpoint kind="udpDiscoveryEndpoint"/> 
      <findCriteria duration="00:00:02"> 
      <types> 
       <add name="IExampleContract"/> 
      </types> 
      <scopes> 
       <add scope="urn://wcf.test.com/examples/exampleContract/development"/> 
      </scopes> 
      </findCriteria> 
     </discoveryClientSettings> 
     </standardEndpoint> 
    </dynamicEndpoint> 
    </standardEndpoints> 
</system.serviceModel> 

이것은 비주얼 스튜디오 2010 SP1을 사용하여 .NET 프레임 워크 4.0에서 타겟으로한다 : 여기

은의 App.config의 관련 부분이다.

DiscoveryClient(string) 생성자에 대한 과부하에 대한 설명은 App.config에 식별 된 구성을 사용하여 DiscoveryClient 인스턴스를 새로 만들어야 함을 나타냅니다.

다른 사람이이 문제가 발생 했습니까? 그렇다면 어떻게 해결 했습니까?

답변

0

좋아요, 나는 Enable .NET Framework source stepping 옵션을 사용하는 디버거에서 많은 시간을 보냈습니다.이 예외가 발생하는 원인은 (아마도) 버그의 구현에 버그가 있다는 것을 발견했습니다. DiscoveryClient은 구성 파일에서 인스턴스화됩니다. null의 하드 코딩 된 값을 contract 매개 변수로 전달하는 호출 스택 아래로 호출 방법이 있으며,이 예외는 원래 예외가 발생하는 곳입니다.

많은 머리를 긁고 많은 검색을 한 후에 다음과 같은 해결 방법을 제안했습니다. (글쎄, 총계는 HACK:입니다!) - 다른 사람들을 돕기 위해 여기 게시했습니다. 같은 문제가 발생합니다. 가되지 않을 수도 있습니다,하지만 난 그 순간에 그것을 테스트 할 수 없습니다 -이 문제는 .NET 프레임 워크 4.5/4.5.1에서 해결 있으리라 믿고있어

// HACK: The following is a workaround for a bug in .NET Framework 4.0 
//  Discovery should be possible when setup from the App.config with the 
//  following three lines of code: 
// 
//   discoveryClient = new DiscoveryClient("DiscoveryEndpoint"); 
//   Collection<EndpointDiscoveryMetadata> serviceCollection = discoveryClient.Find(new FindCriteria(typeof(IExampleContract))).Endpoints; 
//   discoveryClient.Close(); 
// 
//  However, a bug in the Discovery Client implementation results in an 
//  ArgumentNullException when running discovery in this way. 
// 
//  The following code overcomes this limitation by manually parsing the 
//  standard WCF configuration sections of App.config, and then configuring 
//  the appropriate FindCriteria for a programmatically configured discovery 
//  cycle. This code can be replaced by the above three lines when either 
//   1. The bug in .NET Framework 4.0 is resolved (unlikely), or 
//   2. The application is retargeted to .NET Framework 4.5/4.5.1 
// 
//  To aid future developers, this HACK will be extensively documented 

// Load the App.config file into a ConfigurationManager instance and load the configuration 
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 

// Get the ServiceModel configuration group 
ServiceModelSectionGroup serviceModelGroup = ServiceModelSectionGroup.GetSectionGroup(configuration); 

// Get the StandardEndpoints configuration node 
StandardEndpointsSection section = serviceModelGroup.StandardEndpoints; 

// Get the DynamicEndpoint configuration node 
Configuration dynamicEndpointConfiguration = section["dynamicEndpoint"].CurrentConfiguration; 

// Get the first DynamicEndpoint configuration 
// HACK: This assumes only one DynamicEndpoint configuration exists 
//  No additional configurations will be interpreted. This should 
//  not pose a problem as typically a client will only access a 
//  single service instance. This can be extended if necessary 
//  at a later time. 
DynamicEndpointElement element = ((DynamicEndpointElement)serviceModelGroup.StandardEndpoints["dynamicEndpoint"].ConfiguredEndpoints[0]); 

// Set the required Contract Type 
// HACK: This is currently hard-coded to prevent the need to specify 
//  an AssemblyQualifiedName in the App.config file. This will 
//  not typically pose a problem as each client will typically 
//  only open a single service exposing a single, well-known, 
//  Contract Type 
FindCriteria criteria = new FindCriteria(typeof(IExampleContract)); 

// Add all required Scopes to the FindCriteria instance 
foreach (ScopeElement scopeElement in element.DiscoveryClientSettings.FindCriteria.Scopes) 
{ 
    criteria.Scopes.Add(scopeElement.Scope); 
} 

// Get the Discovery Duration 
criteria.Duration = element.DiscoveryClientSettings.FindCriteria.Duration; 

// Create a new Discovery Client instance 
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint()); 

// Retrieve the matching Service Endpoints via Dynamic Search 
Collection<EndpointDiscoveryMetadata> serviceCollection = discoveryClient.Find(criteria).Endpoints; 

// Close the Discovery Client 
discoveryClient.Close(); 

// HACK: END -- Process the results of Discovery 

참고.

다른 누구에게도 이보다 더 우아하거나 효율적인 대체 솔루션이있는 경우 다른 사용자를 위해 게시하십시오.

1

구성 파일에서 정의한 "DiscoveryEndpoint"는 실제로 DiscoveryClient 끝점이 아닌 서비스 클라이언트 끝점입니다.

다음 작업을해야합니다 :

var exampleContractChannelFactory = new ChannelFactory<IExampleContract>("DiscoveryEndpoint"); 
var exampleContractClient = exampleContractChannelFactory.CreateChannel(); 
// You can now invoke methods on the exampleContractClient 
// The actual service endpoint used by the client will be looked up dynamically 
// by the proxy using the DiscoveryClient class internally.