2012-07-18 30 views
0

我有一個使用Prism的WPF應用程序。有多個WCF客戶端的WPF應用程序

該應用程序加載了幾個模塊。

每個模塊都連接到一個或多個WCF服務。

連接詳細信息位於模塊庫的'app.config'文件中。

我的問題是:我如何讓'Shell'項目瞭解在不同程序集中的不同'app.config'文件中傳播的端點配置。

在不同的「模塊」,它試圖連接每個客戶端 - 拋出一個異常的「端點」信息無法找到...

回答

1

UPDATE:

另一種可能的解決方案是創建WCF客戶端在他們自己的AppDomain中。

看到這裏的一些想法:

我想這個問題是如何得到這個與棱鏡工作,祕訣可能是有一個自定義IModuleManager(Prism V4),IModuleLoader(V1)或目錄來處理加載你的WCF客戶端模塊,或者可能有一個包裝模塊t帽子反過來加載你的WCF客戶端。


我在做類似的東西,你在做什麼的第一次嘗試是在我的DLL模塊,這樣做是爲了破解的AppDomain配置。

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! :O /。由於某種原因,它很脆弱......我不記得我的頭頂。

我也嘗試在運行時從ConfigurationManager訪問ServiceModel配置,並試圖通過代碼修改它......但它沒有它。

無論如何,我不認爲上述將幫助你,因爲你將加載多個模塊,所以需要加載多個配置。從

ExceptionHandlingProxyBase<T> 


所以嘗試上述後無論如何我切換到較不脆方法通過使用的組合

CustomClientChannelFactory<T>

我把一些必要的修正得到的ChannelFactory上班,我修改了它,所以我能選擇我是否想用自己的配置覆蓋離子文件,並支持覆蓋地址。

我用ExceptionHandlingProxyBase中此構造函數創建工廠:

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

可以忽略此解決方案的一部分ExceptionHandlingProxyBase ...這就是糖是重新建立通道每當通道故障,這樣您就不必擔心代理的狀態。

如果您仍然不想使用ChannelFactory,那麼您可以嘗試在您的AppDomain中黑客入侵ServiceModel配置。我試過了,但它似乎很難修改

以下是修復了(愚蠢地重命名爲CustomClientChannel)的ChannelFactory代碼。

/// <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

感謝你,在你的鏈接中提到的方法看起來不錯,但閱讀評論 - 看起來好像有相當多的錯誤使用這種方法。此外,我並不總是使用'​​頻道工廠',所以這種方法可能並不總是我... – 2012-07-31 07:26:06

+0

會很高興,如果您更新您的答案與您的解決方案,一旦你找到它...... :) – 2012-07-31 07:26:23

+0

更好的解決方案在這裏:http://stackoverflow.com/questions/5045916/wcf-channelfactory-configuration-outside-of-app-config – 2012-08-01 21:16:10

相關問題