솔루션
-Rory
덕분에, 내가 해낸 :
가 처음에 나는 방법 (1) 바라 보았다하지만 AddStoredProcedureName 및 WriteStoredProcedureName을 전달하는 방법을 나에게 분명 아니었다 애트리뷰트를 내 사용자 지정 tracelistener에 전달하거나 데이터베이스 개체를 만드는 방법도 없으므로 일반적으로 ConfigurationSource를 사용하는 팩터 리 메서드를 통해 수행됩니다. (나는 비 Entlib db 객체를 사용할 수 있다고 생각하지만, 대부분 db 로직을 다시 작성하지 않고 FormattedDatabaseTraceListener에서 대부분 & 붙여 넣기를 복사하려고합니다.)
그래서 내가 얻은 해결책은 위의 (2)를 기반으로합니다. 나는 FileConfigurationSource를 래핑 새로운 IConfigurationSource을 만들 수 있지만 GetSection는 ("connectionStrings")이라고 할 때 먼저 ConnectionStringSettings 레지스트리에서 대신 파일에서 검색 내 사용자 지정 연결 문자열 표현과 ConnectionStringsSection 웁니다
public class PSConfigurationSource : IConfigurationSource
{
/// <summary>
/// Name of the connection string that will be set to use the standard connection
/// string from the registry. Anything wanting to reference the RM database should
/// reference this connection string name.
/// </summary>
private const string RMDatabaseName = "RMDatabase";
private IConfigurationSource wrappedSource;
private ConnectionStringsSection cxnStringsSection;
/// <summary>
/// Creates a PSConfigurationSource based on the wrappedSource.
/// </summary>
/// <param name="wrappedSource"></param>
public PSConfigurationSource(IConfigurationSource wrappedSource)
{
this.wrappedSource = wrappedSource;
}
/// <summary>
/// Retrieves the specified <see cref="T:System.Configuration.ConfigurationSection"/>,
/// unless the connectionStrings section is requested in which case our custom
/// config section is returned, which contains our custom connection string.
/// </summary>
/// <param name="sectionName">The name of the section to be retrieved.</param>
/// <returns>
/// The specified <see cref="T:System.Configuration.ConfigurationSection"/>, or <see langword="null"/> (<b>Nothing</b> in Visual Basic)
/// if a section by that name is not found.
/// </returns>
public ConfigurationSection GetSection(string sectionName)
{
if (sectionName=="connectionStrings")
{
EnsureConnectionStringsSectionSet();
return cxnStringsSection;
}
return wrappedSource.GetSection(sectionName);
}
/// <summary>
/// Sets the cxnStringsSection object, populating it with our standard connection
/// string retrieved from the registry.
/// </summary>
private void EnsureConnectionStringsSectionSet()
{
if (cxnStringsSection == null)
{
// Get the connectionStrings section from the config file.
ConfigurationSection configSection = wrappedSource.GetSection("connectionStrings");
if ((configSection != null) && (configSection is ConnectionStringsSection))
cxnStringsSection = configSection as ConnectionStringsSection;
else
cxnStringsSection = new ConnectionStringsSection();
// Add in the RM database settings. Seems that ConnectionStringSettingsCollection[<string>] doesn't have a setter,
// despite it being in the documentation, so need to remove then add in case it's already there.
cxnStringsSection.ConnectionStrings.Remove(RMDatabaseName);
cxnStringsSection.ConnectionStrings.Add(new ConnectionStringSettings(
RMDatabaseName, SomeStaticHelperClass.GetConnectionStringFromRegistry(), "System.Data.SqlClient"));
}
}
#region WrappedMethods
/// <summary>
/// Adds a <see cref="T:System.Configuration.ConfigurationSection"/> to the configuration source location specified by
/// <paramref name="saveParameter"/> and saves the configuration source.
/// </summary>
/// <remarks>
/// If a configuration section with the specified name already exists in the location specified by
/// <paramref name="saveParameter"/> it will be replaced.
/// </remarks>
/// <param name="saveParameter">The <see cref="T:Microsoft.Practices.EnterpriseLibrary.Common.Configuration.IConfigurationParameter"/> that represents the location where
/// to save the updated configuration.</param><param name="sectionName">The name by which the <paramref name="configurationSection"/> should be added.</param><param name="configurationSection">The configuration section to add.</param>
public void Add(IConfigurationParameter saveParameter, string sectionName, ConfigurationSection configurationSection)
{
wrappedSource.Add(saveParameter, sectionName, configurationSection);
}
/// <summary>
/// Removes a <see cref="T:System.Configuration.ConfigurationSection"/> from the configuration source location specified by
/// <paramref name="removeParameter"/> and saves the configuration source.
/// </summary>
/// <param name="removeParameter">The <see cref="T:Microsoft.Practices.EnterpriseLibrary.Common.Configuration.IConfigurationParameter"/> that represents the location where
/// to save the updated configuration.</param><param name="sectionName">The name of the section to remove.</param>
public void Remove(IConfigurationParameter removeParameter, string sectionName)
{
wrappedSource.Remove(removeParameter, sectionName);
}
/// <summary>
/// Adds a handler to be called when changes to the section named <paramref name="sectionName"/> are detected.
/// </summary>
/// <param name="sectionName">The name of the section to watch for.</param><param name="handler">The handler for the change event to add.</param>
public void AddSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler)
{
wrappedSource.AddSectionChangeHandler(sectionName, handler);
}
/// <summary>
/// Removes a handler to be called when changes to section
/// <code>
/// sectionName
/// </code>
/// are detected.
/// </summary>
/// <param name="sectionName">The name of the watched section.</param><param name="handler">The handler for the change event to remove.</param>
public void RemoveSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler)
{
wrappedSource.RemoveSectionChangeHandler(sectionName, handler);
}
#endregion
}
을 그런 다음이 기본값 대신 ConfigurationSource를 사용합니다. SomeStaticHelperClass.GetConnectionStringFromRegistry()에 대한 호출은 앱의 다른 곳에서 사용되는 연결 문자열을 가져옵니다. 이 솔루션은 또한 FormattedDatabaseTraceListener의 기능을 재현 할 필요가 없다는 이점이 있습니다. 즉 실제로 데이터베이스 로직을 처리합니다.
PSConfigurationSource를 기본값 대신 사용하려면 정적 메서드를 만들어 PSConfigurationSource를 가져 왔습니다. 대신 일반 EntLib 클래스 ExceptionPolicy 및 로거를 사용하여 내가 그들 각각에 대해 내 네임 스페이스에 새로운 클래스를 생성 (예외 처리 및 로깅) 다음
public class EnvironmentAssistant
{
...
public static IConfigurationSource GetConfigurationSource()
{
return
new PSConfigurationSource(
new FileConfigurationSource(GetConfigFilePath()));
}
...
}
을 : 내 경우에는 내가 EnvironmentAssistant라는 클래스에 넣어. ExceptionPolicy 및 Logger에 대한 코드를 복사하고 MyExceptionPolicy 및 MyLogger로 이름을 바꾸기 만하면됩니다. 그런 다음 몇 가지 사소한 변경을하여 기본 구성 소스 대신에 정적 메서드 GetConfigurationSource()
을 사용합니다.
MyExceptionPolicy (Just Initialise가 수정되었습니다.이 메서드를 추가했는지, 아니면 방금 수정했는지 확실하지 않습니다. 나는 다음을 추가 한 경우에는 HandleFirstException()와 HandleException() 내에서 첫 번째 줄로에 호출을 추가해야합니다)
private static void Initialise()
{
if (defaultFactory == null)
{
// Nested check should mean that locking overhead isn't applied unless necessary,
// and means factory won't be overwritten if two threads hit locked section.
lock (sync)
{
if (defaultFactory == null)
{
exceptionsSource = EnvironmentAssistant.GetConfigurationSource();
defaultFactory = new ExceptionPolicyFactory(exceptionsSource);
}
}
}
}
MyLogger :.
이
private static LogWriterFactory factory = new LogWriterFactory(EnvironmentAssistant.GetConfigurationSource());
...
internal static void TryLogConfigurationFailure(ConfigurationErrorsException configurationException)
{
try
{
DefaultLoggingEventLogger logger = EnterpriseLibraryFactory.BuildUp<DefaultLoggingEventLogger>(EnvironmentAssistant.GetConfigurationSource());
logger.LogConfigurationError(configurationException);
}
catch
{ }
}
그런 다음 내 코드를 통해 내가 사용하는 MyExceptionPolicy.HandleException(ex, "policy name")
또는 MyLogger.Log(...)
기본 EntLib 클래스와 동일합니다.
언제든지 누군가에게 도움이되기를 바랍니다.