또 다른 잠재적 인 해결책은을 만드는 것입니다 WCF 클라이언트는 자신의 AppDomains에 있습니다.
내가 질문 프리즘 작업이 활용하는 방법을 것 같다 ... 트릭이있을 수 있습니다 사용자 지정 IModuleManager (Prism V4), IModuleLoader (V1) 또는 Catalog를 사용하여 WCF 클라이언트 모듈로드를 처리하거나 래퍼 모듈 t 모자는 차례로 WCF 클라이언트를로드합니다.
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);
}
}
}
감사합니다. 링크에 언급 된 접근 방식이 좋지만 댓글을 읽는 중입니다. 그런 접근 방식을 사용하는 버그가있는 것처럼 보입니다. 또한, 항상 '채널 팩토리'를 사용하지 않기 때문에 항상 방법이 스위트 룸이 아닐 수도 있습니다. –
일단 해결책을 찾으면 답변을 업데이트하면 행복 할 것입니다. :) –
더 나은 해결책은 여기에 있습니다. : http://stackoverflow.com/questions/5045916/wcf-channelfactory-configuration-outside-of-app-config –