2012-07-18 2 views
0

프리즘을 사용하는 WPF 응용 프로그램이 있습니다.여러 WCF 클라이언트가있는 WPF 응용 프로그램

응용 프로그램이 여러 모듈을로드합니다.

각 모듈은 하나 이상의 WCF 서비스에 연결됩니다.

연결 세부 정보는 모듈 라이브러리의 'app.config'파일에 있습니다.

내 질문입니다 - 다른 어셈블리의 'app.config'파일에 걸쳐있는 끝점 구성에 대해 'Shell'프로젝트에서 어떻게 알 수 있습니까?

는 연결을 시도하는 다른 '모듈'의 각 클라이언트가

- '엔드 포인트'정보를 찾을 수 없다는 예외가 발생합니다 ...

답변

1

UPDATE :

또 다른 잠재적 인 해결책은을 만드는 것입니다 WCF 클라이언트는 자신의 AppDomains에 있습니다.

은 몇 가지 아이디어 여기를 참조하십시오 :

내가 질문 프리즘 작업이 활용하는 방법을 것 같다 ... 트릭이있을 수 있습니다 사용자 지정 IModuleManager (Prism V4), IModuleLoader (V1) 또는 Catalog를 사용하여 WCF 클라이언트 모듈로드를 처리하거나 래퍼 모듈 t 모자는 차례로 WCF 클라이언트를로드합니다.

http://blog.thomaslebrun.net/2011/11/prism-load-modules-in-specific-order-even-for-modules-loaded-on-demand/#.UBpGtU1mSHU

  • https://prism.svn.codeplex.com/svn/V1/spikes/AGCompositeApplicationLibrary/AGComposite/Modularity/ModuleLoader.cs

    • (이것은 단지 참조 ... 프리즘 V1 내지).


    당신이 무엇을하고 있는지에 비슷한 일을에서 내 첫 번째 시도는 내 DLL 모듈이를 수행하여 응용 프로그램 도메인 구성을 해킹했다.

    object o = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE"); 
    
        // See if there is a configuration defined by the Exe host, hosting this DLL. 
    
        Configuration con = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
    
        // Do we need to override the configuration, to point to our "default" one? 
    
        if (con.HasFile == false) 
        { 
         string sFullPathToConfig = Assembly.GetExecutingAssembly().Location + ".config"; 
    
         AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", sFullPathToConfig); 
    
         ConfigurationManager.RefreshSection("system.serviceModel"); 
         ConfigurationManager.RefreshSection("system.diagnostics"); 
        } 
    

    내가 정확히 기억하지 수는 없지만, 내가 (교체 시도에서 충돌을 달리이있을 것입니다) 전혀 ServiceModel은 서비스 구성을 정의하지 내 주 응용 프로그램의 app.config에 있다고 생각 ... 그 반대일지도 모르다, 또는 전혀 app.config를 가지지 않았을지도 모른다! :영형/. 그것은 어떤 이유로 든 취 약했습니다 .... 나는 내 머리 꼭대기에서 기억이 안납니다.

    또한 런타임에 ConfigurationManager에서 ServiceModel 구성에 액세스하려고 시도했지만 코드를 수정하려고했지만 아무 것도 사용하지 않았습니다.

    여하튼, 여러 개의 모듈을로드 할 때마다 위의 내용이 도움이된다고 생각하지 않으므로 여러 개의 config를로드해야합니다.

    에서

    ExceptionHandlingProxyBase<T> 
    

    :


    그래서 여하튼 상기 시도 후 난의 조합을 사용하여 적은 취성 방법으로 전환,451,515,

    CustomClientChannelFactory<T>

    나는 ChannelFactory에 일하러 가야 할 몇 가지 필요한 수정에 넣어, 나는 그것을 수정 그래서 내가 할 수에서 내 자신의 구성으로 오버라이드하고 싶다면 선택하십시오. 이온 파일을 지원하고 주소 재정의를 지원합니다.

    나는 공장 만들기 위해 ExceptionHandlingProxyBase 내에서이 생성자를 사용 :이 솔루션의 ExceptionHandlingProxyBase 부분을 무시할 수

    public CustomClientChannel(Binding binding, string remoteAddress, string configurationPath) 
    

    을 ... 즉 다시 설정 될 때마다 채널 오류 채널을 바로 설탕이다, 따라서 프록시의 상태에 대해 걱정할 필요가 없습니다.

    여전히 ChannelFactory를 사용하고 싶지 않다면 AppDomain에서 ServiceModel 구성을 해킹 할 수 있습니다. 나는 그것을 시도했지만 수정하기가 힘들 것으로 보였다.

    다음은 수정 된 ChannelFactory 코드이다 (CustomClientChannel로 바뀌었다).

    /// <summary> 
    /// Custom client channel. Allows to specify a different configuration file 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    public class CustomClientChannel<T> : ChannelFactory<T> 
    { 
        string configurationPath; 
        string endpointConfigurationName; 
    bool m_bOverrideConfiguration = false; 
    Uri m_OverrideAddress = null; 
    
        /// <summary> 
        /// Constructor 
        /// </summary> 
        /// <param name="configurationPath"></param> 
        public CustomClientChannel(string configurationPath) : base(typeof(T)) 
        { 
         this.configurationPath = configurationPath; 
         base.InitializeEndpoint((string)null, null); 
        } 
    
        /// <summary> 
        /// Constructor 
        /// </summary> 
        /// <param name="binding"></param> 
        /// <param name="configurationPath"></param> 
        public CustomClientChannel(Binding binding, string configurationPath) 
         : this(binding, (EndpointAddress)null, configurationPath) 
    
        { 
        } 
    
        /// <summary> 
        /// Constructor 
        /// </summary> 
        /// <param name="serviceEndpoint"></param> 
        /// <param name="configurationPath"></param> 
        public CustomClientChannel(ServiceEndpoint serviceEndpoint, string configurationPath) 
         : base(typeof(T)) 
        { 
         this.configurationPath = configurationPath; 
         base.InitializeEndpoint(serviceEndpoint); 
        } 
    
        /// <summary> 
        /// Constructor 
        /// </summary> 
        /// <param name="endpointConfigurationName"></param> 
        /// <param name="configurationPath"></param> 
        public CustomClientChannel(string endpointConfigurationName, string configurationPath) 
         : this(endpointConfigurationName, null, configurationPath) 
        { 
        } 
    
        /// <summary> 
        /// Constructor 
        /// </summary> 
        /// <param name="binding"></param> 
        /// <param name="endpointAddress"></param> 
        /// <param name="configurationPath"></param> 
        public CustomClientChannel(Binding binding, EndpointAddress endpointAddress, string configurationPath) 
         : base(typeof(T)) 
        { 
         this.configurationPath = configurationPath; 
         base.InitializeEndpoint(binding, endpointAddress); 
        } 
    
        /// <summary> 
        /// Constructor 
        /// </summary> 
        /// <param name="binding"></param> 
        /// <param name="remoteAddress"></param> 
        /// <param name="configurationPath"></param> 
        public CustomClientChannel(Binding binding, string remoteAddress, string configurationPath) 
         : this(binding, new EndpointAddress(remoteAddress), configurationPath) 
        { 
        } 
    
        /// <summary> 
        /// Constructor 
        /// </summary> 
        /// <param name="endpointConfigurationName"></param> 
        /// <param name="endpointAddress"></param> 
        /// <param name="configurationPath"></param> 
        public CustomClientChannel(string endpointConfigurationName, EndpointAddress endpointAddress, string configurationPath) 
         : base(typeof(T)) 
        { 
        m_OverrideAddress = (endpointAddress != null ? endpointAddress.Uri : null); 
    
         this.configurationPath = configurationPath; 
         this.endpointConfigurationName = endpointConfigurationName; 
         base.InitializeEndpoint(endpointConfigurationName, endpointAddress); 
        } 
    
        /// <summary> 
        /// Loads the serviceEndpoint description from the specified configuration file 
        /// </summary> 
        /// <returns></returns> 
        protected override ServiceEndpoint CreateDescription() 
        { 
        if (string.IsNullOrEmpty(this.configurationPath)) 
        { 
         System.Diagnostics.Debug.WriteLine("Not using overriding config file"); 
    
         return base.CreateDescription(); 
        } 
    
        if (!System.IO.File.Exists(configurationPath)) 
        { 
         System.Diagnostics.Debug.WriteLine("Overriding config file [" + configurationPath + "] doesn't exist"); 
    
         return base.CreateDescription(); 
        } 
    
        m_bOverrideConfiguration = true; 
    
         ServiceEndpoint serviceEndpoint = base.CreateDescription(); 
    
         if (endpointConfigurationName != null) 
          serviceEndpoint.Name = endpointConfigurationName; 
    
         ExeConfigurationFileMap map = new ExeConfigurationFileMap(); 
         map.ExeConfigFilename = this.configurationPath; 
    
         Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); 
         ServiceModelSectionGroup group = ServiceModelSectionGroup.GetSectionGroup(config); 
    
         ChannelEndpointElement selectedEndpoint = null; 
    
         foreach (ChannelEndpointElement endpoint in group.Client.Endpoints) 
         { 
          if (endpoint.Contract == serviceEndpoint.Contract.ConfigurationName && 
           (this.endpointConfigurationName == null || this.endpointConfigurationName == endpoint.Name)) 
          { 
           selectedEndpoint = endpoint; 
           break; 
          } 
         } 
    
         if (selectedEndpoint != null) 
         { 
          if (serviceEndpoint.Binding == null) 
          { 
           serviceEndpoint.Binding = CreateBinding(selectedEndpoint.Binding, selectedEndpoint.BindingConfiguration, group); 
          } 
    
         if (m_OverrideAddress != null) 
         { 
          serviceEndpoint.Address = new EndpointAddress(m_OverrideAddress, GetIdentity(selectedEndpoint.Identity), selectedEndpoint.Headers.Headers); 
         } 
         else 
          if (serviceEndpoint.Address == null) 
          { 
           serviceEndpoint.Address = new EndpointAddress(selectedEndpoint.Address, GetIdentity(selectedEndpoint.Identity), selectedEndpoint.Headers.Headers); 
          } 
    
          if (serviceEndpoint.Behaviors.Count == 0 && !string.IsNullOrEmpty(selectedEndpoint.BehaviorConfiguration)) 
          { 
           AddBehaviors(selectedEndpoint.BehaviorConfiguration, serviceEndpoint, group); 
          } 
    
          serviceEndpoint.Name = selectedEndpoint.Contract; 
         } 
    
         return serviceEndpoint; 
    
        } 
    
        /// <summary> 
        /// Configures the binding for the selected endpoint 
        /// </summary> 
        /// <param name="bindingName"></param> 
        /// <param name="group"></param> 
        /// <returns></returns> 
        private Binding CreateBinding(string bindingName, string bindingConfiguration, ServiceModelSectionGroup group) 
        { 
        IBindingConfigurationElement be = null; 
    
         BindingCollectionElement bindingElementCollection = group.Bindings[bindingName]; 
    
        if (bindingElementCollection.ConfiguredBindings.Count > 0) 
        { 
    
         foreach (IBindingConfigurationElement bindingElem in bindingElementCollection.ConfiguredBindings) 
         { 
    
          if (string.Compare(bindingElem.Name, bindingConfiguration) == 0) 
          { 
    
           be = bindingElem; 
    
           break; 
    
          } 
    
         } 
    
         Binding binding = null; 
    
         if (be != null) 
         { 
    
          binding = GetBinding(be); 
    
          be.ApplyConfiguration(binding); 
    
         } 
    
         return binding; 
    
        } 
    
        return null; 
        } 
    
        /// <summary> 
        /// Helper method to create the right binding depending on the configuration element 
        /// </summary> 
        /// <param name="configurationElement"></param> 
        /// <returns></returns> 
        private Binding GetBinding(IBindingConfigurationElement configurationElement) 
        { 
         if (configurationElement is CustomBindingElement) 
          return new CustomBinding(); 
         else if (configurationElement is BasicHttpBindingElement) 
          return new BasicHttpBinding(); 
         else if (configurationElement is NetMsmqBindingElement) 
          return new NetMsmqBinding(); 
         else if (configurationElement is NetNamedPipeBindingElement) 
          return new NetNamedPipeBinding(); 
         else if (configurationElement is NetPeerTcpBindingElement) 
          return new NetPeerTcpBinding(); 
         else if (configurationElement is NetTcpBindingElement) 
          return new NetTcpBinding(); 
         else if (configurationElement is WSDualHttpBindingElement) 
          return new WSDualHttpBinding(); 
         else if (configurationElement is WSHttpBindingElement) 
          return new WSHttpBinding(); 
         else if (configurationElement is WSFederationHttpBindingElement) 
          return new WSFederationHttpBinding(); 
    
         return null; 
        } 
    
        /// <summary> 
        /// Adds the configured behavior to the selected endpoint 
        /// </summary> 
        /// <param name="behaviorConfiguration"></param> 
        /// <param name="serviceEndpoint"></param> 
        /// <param name="group"></param> 
        private void AddBehaviors(string behaviorConfiguration, ServiceEndpoint serviceEndpoint, ServiceModelSectionGroup group) 
        { 
        if (group.Behaviors.EndpointBehaviors.Count == 0) 
         return; 
    
         EndpointBehaviorElement behaviorElement = group.Behaviors.EndpointBehaviors[behaviorConfiguration]; 
         for (int i = 0; i < behaviorElement.Count; i++) 
         { 
          BehaviorExtensionElement behaviorExtension = behaviorElement[i]; 
          object extension = behaviorExtension.GetType().InvokeMember("CreateBehavior", 
           BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, 
           null, behaviorExtension, null); 
          if (extension != null) 
          { 
           serviceEndpoint.Behaviors.Add((IEndpointBehavior)extension); 
          } 
         } 
        } 
    
        /// <summary> 
        /// Gets the endpoint identity from the configuration file 
        /// </summary> 
        /// <param name="element"></param> 
        /// <returns></returns> 
        private EndpointIdentity GetIdentity(IdentityElement element) 
        { 
         EndpointIdentity identity = null; 
         PropertyInformationCollection properties = element.ElementInformation.Properties; 
         if (properties["userPrincipalName"].ValueOrigin != PropertyValueOrigin.Default) 
         { 
          return EndpointIdentity.CreateUpnIdentity(element.UserPrincipalName.Value); 
         } 
         if (properties["servicePrincipalName"].ValueOrigin != PropertyValueOrigin.Default) 
         { 
          return EndpointIdentity.CreateSpnIdentity(element.ServicePrincipalName.Value); 
         } 
         if (properties["dns"].ValueOrigin != PropertyValueOrigin.Default) 
         { 
          return EndpointIdentity.CreateDnsIdentity(element.Dns.Value); 
         } 
         if (properties["rsa"].ValueOrigin != PropertyValueOrigin.Default) 
         { 
          return EndpointIdentity.CreateRsaIdentity(element.Rsa.Value); 
         } 
         if (properties["certificate"].ValueOrigin != PropertyValueOrigin.Default) 
         { 
          X509Certificate2Collection supportingCertificates = new X509Certificate2Collection(); 
          supportingCertificates.Import(Convert.FromBase64String(element.Certificate.EncodedValue)); 
          if (supportingCertificates.Count == 0) 
          { 
           throw new InvalidOperationException("UnableToLoadCertificateIdentity"); 
          } 
          X509Certificate2 primaryCertificate = supportingCertificates[0]; 
          supportingCertificates.RemoveAt(0); 
          return EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate, supportingCertificates); 
         } 
    
         return identity; 
        } 
    
    
        protected override void ApplyConfiguration(string configurationName) 
        { 
        if (!m_bOverrideConfiguration) 
        { 
         // This picks up the configuration from the inherited config settings defined 
         // by the application i.e. the normal place. 
    
         base.ApplyConfiguration(configurationName); 
        } 
        } 
    } 
    
  • +0

    감사합니다. 링크에 언급 된 접근 방식이 좋지만 댓글을 읽는 중입니다. 그런 접근 방식을 사용하는 버그가있는 것처럼 보입니다. 또한, 항상 '채널 팩토리'를 사용하지 않기 때문에 항상 방법이 스위트 룸이 아닐 수도 있습니다. –

    +0

    일단 해결책을 찾으면 답변을 업데이트하면 행복 할 것입니다. :) –

    +0

    더 나은 해결책은 여기에 있습니다. : http://stackoverflow.com/questions/5045916/wcf-channelfactory-configuration-outside-of-app-config –