C # DLL 구성 파일 ‘ DLL에 구성 정보 넣기 ‘의 MusicGenesis에

app.config 파일을 DLL에 추가하려고 시도했지만 모든 시도가 실패했습니다.

DLL에 구성 정보 넣기 ‘의 MusicGenesis에 따르면 이것은 문제가되지 않습니다. 분명히 나는 ​​뭔가 잘못하고 있습니다 …

다음 코드는 DLL에서 ConnectionString을 반환해야합니다.

return ConfigurationManager.AppSettings["ConnectionString"];

그러나 app.config 파일을 콘솔 응용 프로그램에 복사하면 정상적으로 작동합니다.

어떤 아이디어?



답변

.DLL에 대한 .NET 구성 파일을 작성하는 것은 쉬운 일이 아닙니다. .NET 구성 메커니즘에는 앱을 쉽게 업그레이드 / 업데이트하고 설치된 앱이 서로 구성 파일을 짓밟 지 않도록 보호하기 위해 많은 기능이 내장되어 있습니다.

DLL 사용 방법과 응용 프로그램 사용 방법에는 큰 차이가 있습니다. 동일한 사용자에 대해 동일한 시스템에 여러 응용 프로그램 사본이 설치되어 있지 않을 수 있습니다. 그러나 일부 .NET DLL을 사용하는 100 개의 서로 다른 앱이나 라이브러리가있을 수 있습니다.

하나 개의 사용자 프로파일 내 응용 프로그램의 다른 복사본을 별도로 설정을 추적 할 필요가 거의 없다 반면, 그건 아주 당신이 서로 공유 구성에 DLL의 다른 사용법을 모두 원하는 것 같지는. 이러한 이유로 “일반”방법을 사용하여 Configuration 개체를 검색하면 반환 한 개체가 특정 어셈블리가 아닌 실행중인 App Domain의 구성에 연결됩니다.

앱 도메인은 코드가 실제로있는 어셈블리를로드 한 루트 어셈블리에 바인딩됩니다. 대부분의 경우 이는 .DLL을로드 한 기본 .EXE 어셈블리입니다. 응용 프로그램 내에서 다른 응용 프로그램 도메인을 스핀 업할 수 있지만 해당 응용 프로그램 도메인의 루트 어셈블리에 대한 정보를 명시 적으로 제공해야합니다.

이 때문에 라이브러리 특정 구성 파일을 작성하는 절차는 그리 편리하지 않습니다. 그것은 당신이 특정 어셈블리에 연결되지 않은 임의의 휴대용 설정 파일을 만드는 데 사용하는 것과 같은 과정이지만있는 당신은 부와 구성 요소 메커니즘 등 생성이 수반 구성, .NET의 XML 스키마를 사용하려는 ExeConfigurationFileMap객체를 구성 파일을 저장할 위치를 식별하기 위해 데이터를로드 한 다음을 호출 ConfigurationManager합니다. OpenMappedExeConfigurationConfiguration인스턴스 로 엽니 다 . 이 것입니다 자동 경로 생성 메커니즘에 의해 제공되는 버전의 보호에서 당신을 잘라.

통계적으로 말하면, 사내 환경에서이 라이브러리를 사용하고있을 것이므로 한 컴퓨터 / 사용자 내에서 여러 앱을 사용하지는 않을 것입니다. 그러나 그렇지 않은 경우 명심해야 할 것이 있습니다. 참조하는 앱에 관계없이 DLL에 단일 전역 구성 파일을 사용하는 경우 액세스 충돌에 대해 걱정해야합니다. 라이브러리를 참조하는 두 개의 앱이 각각 자체 Configuration개체가 열린 상태 에서 동시에 실행되는 경우 변경 사항을 저장하면 다음에 다른 앱에서 데이터를 검색하거나 저장하려고 할 때 예외가 발생합니다.

이 문제를 해결하는 가장 안전하고 간단한 방법은 DLL을로드하는 어셈블리도 자체에 대한 정보를 제공하거나 참조 어셈블리의 App Domain을 검사하여 감지하는 것입니다. 이를 사용하여 DLL을 참조하는 각 앱에 대해 별도의 사용자 구성 파일을 유지하기위한 일종의 폴더 구조를 만듭니다.

당신이 경우 특정 당신이 참조하는 위치에 상관없이 당신의 DLL에 대한 전역 설정이없는하려면, 당신은 그것을위한 당신의 위치를 결정하지 않고 .NET보다는 자동으로 적절한 일을 파악해야합니다. 또한 파일에 대한 액세스 관리에 적극적이어야합니다. Configuration인스턴스를로드하거나 저장하는 동안 인스턴스를 유지하고 가능한 한 많이 캐시해야합니다. 바로 앞을 열고 즉시 버립니다. 마지막으로 라이브러리를 사용하는 앱 중 하나에서 파일을 편집하는 동안 파일을 보호하려면 잠금 메커니즘이 필요합니다.


답변

루트 응용 프로그램 web.config 또는 app.config가 아닌 DLL의 구성 파일에서 설정을 읽으려면 아래 코드를 사용하여 dll의 구성을 읽으십시오.

var appConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
string dllConfigData = appConfig.AppSettings.Settings["dllConfigData"].Value;

답변

나는 같은 문제를 겪었고 몇 시간 동안 웹을 검색했지만 해결책을 찾지 못해 스스로 만들었습니다. .net 구성 시스템이 왜 그렇게 융통성이 없는지 궁금했습니다.

배경 : 데이터베이스 및 DAL 설정을위한 자체 구성 파일을 갖도록 DAL.dll을 갖고 싶습니다. 또한 엔터프라이즈 라이브러리 및 자체 구성을위한 app.config가 필요합니다. 따라서 app.config와 dll.config가 모두 필요합니다.

내가 원하지 않는 것은 앱에서 내 DAL 레이어로 모든 속성 / 설정을 전달하는 것입니다!

정상적인 app.config 동작에 필요하기 때문에 “AppDomain.CurrentDomain.SetupInformation.ConfigurationFile”을 구부릴 수 없습니다.

내 요구 사항 / 관점은 다음과 같습니다.

  • 다른 개발자는 재현 할 수 없으므로 ClassLibrary1.dll.config에서 WindowsFormsApplication1.exe.config로 수동 복사 할 수 없습니다.
  • 이것이 중요한 기능이라고 생각하고 잃고 싶지 않기 때문에 강력한 타이핑 “Properties.Settings.Default.NameOfValue”(설정 동작)의 사용법을 유지하십시오.
  • 자체 / 사용자 정의 구성 파일 또는 관리를 주입 할 ApplicationSettingsBase가 부족하다는 것을 알았습니다 (필수 필드는 모두이 클래스에서 비공개입니다)
  • ClassLibrary1.dll.config를 복사 / 재 작성하고 여러 섹션에 대해 여러 XML 파일을 제공해야하므로 “configSource”파일 리디렉션을 사용할 수 없습니다 (이 또한 마음에 들지 않았습니다)
  • MSDN이 제안한 것처럼이 간단한 작업에 대해 내 자신의 SettingsProvider를 작성하고 싶지 않았습니다.
  • 구성 파일의 applicationSettings 및 connectionStrings 섹션 만 필요합니다.

Settings.cs 파일을 수정하고 ClassLibrary1.dll.config를 열고 개인 필드에서 섹션 정보를 읽는 방법을 구현했습니다. 그런 다음 “this [string propertyName]”을 재정 의하여 생성 된 Settings.Desginer.cs가 기본 클래스 대신 새 속성을 호출합니다. 설정이 목록에서 읽 힙니다.

마지막으로 다음 코드가 있습니다.

internal sealed partial class Settings
{
    private List<ConfigurationElement> list;

    /// <summary>
    /// Initializes a new instance of the <see cref="Settings"/> class.
    /// </summary>
    public Settings()
    {
        this.OpenAndStoreConfiguration();
    }

    /// <summary>
    /// Opens the dll.config file and reads its sections into a private List of ConfigurationElement.
    /// </summary>
    private void OpenAndStoreConfiguration()
    {
        string codebase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
        Uri p = new Uri(codebase);
        string localPath = p.LocalPath;
        string executingFilename = System.IO.Path.GetFileNameWithoutExtension(localPath);
        string sectionGroupName = "applicationSettings";
        string sectionName = executingFilename + ".Properties.Settings";
        string configName = localPath + ".config";
        ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = configName;
        Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

        // read section of properties
        var sectionGroup = config.GetSectionGroup(sectionGroupName);
        var settingsSection = (ClientSettingsSection)sectionGroup.Sections[sectionName];
        list = settingsSection.Settings.OfType<ConfigurationElement>().ToList();

        // read section of Connectionstrings
        var sections = config.Sections.OfType<ConfigurationSection>();
        var connSection = (from section in sections
                           where section.GetType() == typeof(ConnectionStringsSection)
                           select section).FirstOrDefault() as ConnectionStringsSection;
        if (connSection != null)
        {
            list.AddRange(connSection.ConnectionStrings.Cast<ConfigurationElement>());
        }
    }

    /// <summary>
    /// Gets or sets the <see cref="System.Object"/> with the specified property name.
    /// </summary>
    /// <value></value>
    public override object this[string propertyName]
    {
        get
        {
            var result = (from item in list
                         where Convert.ToString(item.ElementInformation.Properties["name"].Value) == propertyName
                         select item).FirstOrDefault();
            if (result != null)
            {
                if (result.ElementInformation.Type == typeof(ConnectionStringSettings))
                {
                    return result.ElementInformation.Properties["connectionString"].Value;
                }
                else if (result.ElementInformation.Type == typeof(SettingElement))
                {
                    return result.ElementInformation.Properties["value"].Value;
                }
            }
            return null;
        }
        // ignore
        set
        {
            base[propertyName] = value;
        }
    }

ClassLibrary1 출력 디렉토리에서 애플리케이션의 출력 디렉토리로 ClassLibrary1.dll.config를 복사하면됩니다. 아마도 누군가가 유용하다고 생각할 것입니다.


답변

ConfigurationManager를 사용할 때 프로세스 / AppDomain구성 파일 (app.config / web.config)을 로드하고 있다고 확신합니다 . 특정 구성 파일을로드하려면 해당 파일을 이름별로 요청해야합니다.

시도해 볼 수 있습니다 :

var config = ConfigurationManager.OpenExeConfiguration("foo.dll");
config.ConnectionStrings. [etc]

답변

ConfigurationManager.AppSettings는 특정 DLL이 아니라 응용 프로그램에 대해 정의 된 설정을 반환합니다.이 설정에는 액세스 할 수 있지만 반환되는 응용 프로그램 설정입니다.

다른 응용 프로그램에서 dll을 사용하는 경우 ConnectionString은 응용 프로그램의 app.settings에 있어야합니다.


답변

나는 이것이 파티에 늦었다는 것을 알고 있지만 DLL에 사용하는 솔루션을 공유 할 것이라고 생각했습니다.

나는 KISS 사고에 더 가깝기 때문에 어떻게 작동하는지 또는 어디로 가는지를 제어하는 ​​외부 데이터 포인트를 저장하려는 .NET DLL이있을 때 단순히 공용 속성 만있는 “config”클래스를 만듭니다. 필요한 모든 데이터 포인트를 저장하고 변경을 위해 다시 컴파일하지 않도록 DLL 외부에서 제어 할 수 있기를 바랍니다. 그런 다음 .Net의 XML Serializing을 사용하여 클래스의 객체 표현을 저장하고 파일로로드합니다.

정적 유틸리티 클래스 인 Singleton에서 확장 메서드에 이르기까지 읽기 및 액세스를 처리하는 방법에는 여러 가지가 있습니다. 이는 DLL의 구성 방식과 DLL에 가장 적합한 방법에 따라 다릅니다.


답변

맞습니다. dll의 구성 파일을 읽을 수 있습니다. 내 구성 파일이 문제라는 것을 알 때까지 하루 동안이 문제로 어려움을 겪었습니다. 아래 코드를 참조하십시오. 달릴 수있었습니다.

        ExeConfigurationFileMap map = new ExeConfigurationFileMap();
        map.ExeConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
        Configuration libConfig = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
        AppSettingsSection section = (libConfig.GetSection("appSettings") as AppSettingsSection);
        Console.WriteLine(section.Settings["dnd_shortcodes"].Value);

Plugin1.dll.config모습은 아래와 같습니다.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <appSettings>
  <add key="cmd_location" value="http://..."/>
  <add key="dnd_shortcodes" value="142,145,146,157,165,167,168,171,173,176,178,404,40"/>
 </appSettings>
</configuration>

내 구성 파일에 <appSettings>태그 가 없다는 것을 알았습니다. 문제를 둘러 보았을 때 문제가 다를 수 있었지만 그렇게 멀지는 않았습니다.