app.config / web.config 내의 변수


92

app.config또는 web.config파일 에서 다음과 같은 작업을 수행 할 수 있습니까?

<appSettings>
 <add key="MyBaseDir" value="C:\MyBase" />
 <add key="Dir1" value="[MyBaseDir]\Dir1"/>
 <add key="Dir2" value="[MyBaseDir]\Dir2"/>
</appSettings>

그런 다음 간단히 다음과 같이 말하여 코드에서 Dir2에 액세스하고 싶습니다.

 ConfigurationManager.AppSettings["Dir2"]

이렇게하면 전체 app.config. (코드의 모든 연결을 관리 할 수 ​​있다는 것을 알고 있지만이 방식을 선호합니다).


나는 그가 구성 파일 내에서 직접 appSettings 키에서 사용할 변수를 정의하는 것에 대해 이야기하고 있다고 생각합니다.
Michaël Carpentier

1
또한 XML <! ENTITY> 선언을 사용하여 체크 아웃했지만 MS가 web.config 파일을 처리하는 방식으로 인해 지원되지 않습니다.
chilltemp

당신의 노력에 감사드립니다. 코드를 수정하지 않는 것을 선호합니다. 코드에는 이미 다음과 같은 명령문이 있습니다. string dir2 = ConfigurationManager.AppSettings [ "Dir2"]. 이제 value = "[MyBaseDir] \ Dir2"대신 value = "D : \ blahdir \ Dir2"라고 표시된 app.config 만 정리하고 싶습니다
DeeStackOverflow

답변:


7

좋은 질문.

나는 없다고 생각합니다. 쉬운 방법이 있었다면 꽤 잘 알려졌을 것이라고 생각하며 Microsoft가 Visual Studio 2010에서 배포 및 테스트를위한 다양한 구성 파일을 배포하기위한 메커니즘을 만들고 있음을 알았습니다.

그러나 그 말로; ConnectionStrings섹션에 "| DataDirectory |"라는 일종의 자리 표시 자가 있음을 발견했습니다 . 거기에서 무슨 일이 일어나고 있는지 살펴볼 수있을 것입니다 ...

다음은 machine.config그것을 보여주는 부분입니다 .

 <connectionStrings>
    <add
        name="LocalSqlServer"
        connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
        providerName="System.Data.SqlClient"
    />
 </connectionStrings>

흥미로운 정보입니다. 파이프 기호 ( "|")를 사용하여 변수에 액세스 할 수 있습니까? 흠 .. 이것이 작동하는지 궁금합니다. <add key = "Dir2"value = "| MyBaseDir | \ Dir2"/>
DeeStackOverflow

4
DataDirectory 값은 실제로 AppDomain의 데이터 요소입니다. AppDomain.CurrentDomain.SetData ( "DataDirectory", dataPath);를 사용하여 값을 재정의 할 수 있습니다. 이 같은 다른 변수를 정의하고 "자동 확장"을 얻을 수 있는지 테스트하지 않았습니다.
Peter Lillevold

22

약간 더 복잡하지만 훨씬 더 유연한 대안은 구성 섹션을 나타내는 클래스를 만드는 것입니다. 당신의에서 app.config/ web.config파일이있을 수 있습니다 :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <!-- This section must be the first section within the <configuration> node -->
    <configSections>
        <section name="DirectoryInfo" type="MyProjectNamespace.DirectoryInfoConfigSection, MyProjectAssemblyName" />
    </configSections>

    <DirectoryInfo>
        <Directory MyBaseDir="C:\MyBase" Dir1="Dir1" Dir2="Dir2" />
    </DirectoryInfo>
</configuration>

그런 다음 .NET 코드 (예에서는 C # 사용)에서 다음과 같은 두 개의 클래스를 만들 수 있습니다.

using System;
using System.Configuration;

namespace MyProjectNamespace {

    public class DirectoryInfoConfigSection : ConfigurationSection {

        [ConfigurationProperty("Directory")]
        public DirectoryConfigElement Directory {
            get {
                return (DirectoryConfigElement)base["Directory"];
            }
    }

    public class DirectoryConfigElement : ConfigurationElement {

        [ConfigurationProperty("MyBaseDir")]
        public String BaseDirectory {
            get {
                return (String)base["MyBaseDir"];
            }
        }

        [ConfigurationProperty("Dir1")]
        public String Directory1 {
            get {
                return (String)base["Dir1"];
            }
        }

        [ConfigurationProperty("Dir2")]
        public String Directory2 {
            get {
                return (String)base["Dir2"];
            }
        }
        // You can make custom properties to combine your directory names.
        public String Directory1Resolved {
            get {
                return System.IO.Path.Combine(BaseDirectory, Directory1);
            }
        }
    }
}

마지막으로 프로그램 코드 app.config에서 다음과 같은 방식으로 새 클래스를 사용하여 변수에 액세스 할 수 있습니다 .

DirectoryInfoConfigSection config =
  (DirectoryInfoConfigSection)ConfigurationManager.GetSection("DirectoryInfo");
String dir1Path = config.Directory.Directory1Resolved;  // This value will equal "C:\MyBase\Dir1"

1
고맙지 만이 단계에서는 고통스럽기 때문에 코드를 수정하지 않고이 작업을 수행하려고합니다.
DeeStackOverflow

코드의 마지막 줄에 작은 오류가 있습니다 (중괄호 제외) : "return System.IO.Path.Combine (MyBaseDir, Dir1);" 대신 "return System.IO.Path.Combine (BaseDirectory, Dir1);"이어야합니다. 그렇지 않으면 메서드의 이름을 'Base Directory'에서 'MyBaseDir'로 변경해야합니다
TheWho

16

내 라이브러리 Expansive를 사용하여 수행 할 수 있습니다 . 여기 에서 nuget에서도 사용할 수 있습니다 .

이를 기본 사용 사례로 설계했습니다.

보통의 예 (AppSettings를 토큰 확장의 기본 소스로 사용)

app.config에서 :

<configuration>
    <appSettings>
        <add key="Domain" value="mycompany.com"/>
        <add key="ServerName" value="db01.{Domain}"/>
    </appSettings>
    <connectionStrings>
        <add name="Default" connectionString="server={ServerName};uid=uid;pwd=pwd;Initial Catalog=master;" provider="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

확장 할 문자열에 .Expand () 확장 메서드를 사용합니다 .

var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
connectionString.Expand() // returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"

또는

다음과 같이 Dynamic ConfigurationManager 래퍼 "Config"를 사용합니다 (Expand ()에 대한 명시 적 호출이 필요하지 않음).

var serverName = Config.AppSettings.ServerName;
// returns "db01.mycompany.com"

var connectionString = Config.ConnectionStrings.Default;
// returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"

고급 예제 1 (토큰 확장을위한 기본 소스로 AppSettings 사용)

app.config에서 :

<configuration>
    <appSettings>
        <add key="Environment" value="dev"/>
        <add key="Domain" value="mycompany.com"/>
        <add key="UserId" value="uid"/>
        <add key="Password" value="pwd"/>
        <add key="ServerName" value="db01-{Environment}.{Domain}"/>
        <add key="ReportPath" value="\\{ServerName}\SomeFileShare"/>
    </appSettings>
    <connectionStrings>
        <add name="Default" connectionString="server={ServerName};uid={UserId};pwd={Password};Initial Catalog=master;" provider="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

확장 할 문자열에 .Expand () 확장 메서드를 사용합니다.

var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
connectionString.Expand() // returns "server=db01-dev.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"

4
나는이 답변이 매우 과소 평가되었다고 생각합니다!
Ahmad

감사합니다 Ahmad! Expansive를 좋아하는 방법을 알려주세요.
anderly

이것은 앱 설정의 런타임 '해상도'이지만 반복적 인 키 값 쌍을 갖는 문제를 해결합니다. 이를 사용하여 구성 유지 관리를 크게 줄였습니다. 여기서 절대적인 유토피아는 이것이 SlowCheetah와 함께 작동하는 빌드 타임 플러그인이되는 것입니다. 할 수 있으면 다시 +1하겠습니다. 대단한 물건.
아마드

이를 위해 귀하의 도서관을 어떻게 사용할 수 있는지에 대한 간단한 예를 제공해 주시겠습니까?
Ryan Gates

다른 지금이 가로 질러 보았 지 누군가를 위해,이 프로젝트는 2011 :( 이후 해주기 6 년 동안 죽은되었습니다
user1003916

4

이 질문을 방금 본 것 같습니다.

요컨대, 애플리케이션 구성 내에 변수 보간이 없습니다.

두 가지 옵션이 있습니다

  1. 런타임에 변수를 대체하기 위해 직접 굴릴 수 있습니다.
  2. 빌드시 대상 배치 환경의 특정 특성에 맞게 애플리케이션 구성을 마사지하십시오. 구성 악몽처리 할 때 이에 대한 몇 가지 세부 사항

이것은 올바른 게시물입니다. 내 이전 게시물 (동일한 질문)에 app.config xml 항목 예제가 표시되지 않았습니다. 나는 당신의 링크를 확인했습니다-너무 많은 작업이며 거기에서 시간을 소비하지 않는 것을 선호합니다. 우리는 다른 상자에 대한 별도의 app.configs를 가지고 있으며 그에서 벗어나고 싶습니다.
DeeStackOverflow

3

몇 가지 옵션이 있습니다. 변수를 올바른 값으로 바꾸는 구성 파일을 처리하는 빌드 / 배포 단계로이를 수행 할 수 있습니다.

또 다른 옵션은이를 지원하는 자체 구성 섹션을 정의하는 것입니다. 예를 들어 다음 xml을 상상해보십시오.

<variableAppSettings>
 <variables>
    <add key="@BaseDir" value="c:\Programs\Widget"/>
 </variables>
 <appSettings>
    <add key="PathToDir" value="@BaseDir\Dir1"/>
 </appSettings>
</variableAppSettings>

이제 런타임에 변수 교체를 처리하는 사용자 지정 구성 개체를 사용하여이를 구현합니다.


게시물에 xml이 표시되지 않습니다 (xml 태그를 게시 할 수 있도록 줄 5 자 들여 쓰기-지난번에 같은 문제가 발생했습니다). 또한 '사용자 지정 구성 개체'란 무엇입니까? 이 단계에서 코딩을 변경하면 많은 것을 되돌릴 수 있으므로 제로 코딩을 선호합니다.
DeeStackOverflow

사용자 지정 구성에는 확실히 [간단한] 코딩이 포함됩니다. 그러나 IMHO는 항상 최선의 선택입니다. 저는 appSettings를 거의 사용하지 않고 대신 모든 프로젝트에 대한 사용자 지정 구성을 만드는 것을 선호합니다.
Portman

3

일반적으로 web.config의 각 설정에 액세스하는 속성이있는 정적 클래스를 작성합니다.

public static class ConfigManager 
{
    public static string MyBaseDir
    {
        return ConfigurationManager.AppSettings["MyBaseDir"].toString();
    }

    public static string Dir1
    {
        return MyBaseDir + ConfigurationManager.AppSettings["Dir1"].toString();
    }

}

일반적으로이 클래스에서 필요할 때 유형 변환도 수행합니다. 구성에 대한 입력 된 액세스를 허용하며 설정이 변경되면 한 곳에서만 편집 할 수 있습니다.

일반적으로 설정을이 클래스로 바꾸는 것은 비교적 쉽고 유지 관리가 훨씬 쉽습니다.


3

app.config설명하는 시나리오에 대해 환경 변수를 사용할 수 있습니다.

<configuration>
  <appSettings>
    <add key="Dir1" value="%MyBaseDir%\Dir1"/>
  </appSettings>
</configuration>

그러면 다음과 같이 쉽게 경로를 얻을 수 있습니다.

var pathFromConfig = ConfigurationManager.AppSettings["Dir1"];
var expandedPath = Environment.ExpandEnvironmentVariables(pathFromConfig);

2

내부에서 <appSettings>애플리케이션 키를 만들 수 있습니다.

<add key="KeyName" value="Keyvalue"/>

나중에 다음을 사용하여 이러한 값에 액세스 할 수 있습니다.

ConfigurationManager.AppSettings["Keyname"]

ConfigurationManager 클래스를 사용하려면 System.Configuration에 대한 참조를 추가하고 System.Configuration에 대한 using 문을 추가해야합니다 (VB에서 가져 오기)
cjk

2
표시는 정확하지만 질문에 대한 답변이 아닙니다.
Michaël Carpentier

1

DslConfig를 제안합니다 . DslConfig를 사용하면 전역 구성, 서버 호스트 별 구성에서 각 서버 호스트의 응용 프로그램 별 구성까지 계층 적 구성 파일을 사용할 수 있습니다 (AppSpike 참조).
이것이 복잡하다면 전역 구성 Variables.var를 사용할 수
있습니다. Varibales.var에서 구성하십시오.

baseDir = "C:\MyBase"
Var["MyBaseDir"] = baseDir
Var["Dir1"] = baseDir + "\Dir1"
Var["Dir2"] = baseDir + "\Dir2"

그리고 구성 값을 가져옵니다.

Configuration config = new DslConfig.BooDslConfiguration()
config.GetVariable<string>("MyBaseDir")
config.GetVariable<string>("Dir1")
config.GetVariable<string>("Dir2")

0

구성 파일 내에서 appSettings 키를 정의하기 위해 변수를 선언하고 사용할 수 없다고 생각합니다. 나는 항상 당신과 같은 코드에서 연결을 관리했습니다.


0

나는 당신이 원하는 것에 약간 어려움을 겪고 있지만, 앱 설정에 재정의 파일을 추가 한 다음 해당 재정의 파일을 환경별로 설정할 수 있습니다.

<appSettings file="..\OverrideSettings.config">

0

비슷한 값을 가진 많은 항목을 구성해야하는 제품을 출시하기 위해 XML을 읽고 전달 된 매개 변수를 기반으로 업데이트하는 작은 콘솔 앱을 사용합니다. 그런 다음 사용자에게 요청한 후 설치 프로그램에서 호출합니다. 필수 정보.


0

Matt Hamsmith의 솔루션을 따르는 것이 좋습니다. 구현하는 것이 문제라면 AppSettings 클래스의 백그라운드에서이를 구현하는 확장 메서드를 만드는 것은 어떻습니까?

다음과 같은 것 :

    public static string GetValue(this NameValueCollection settings, string key)
    {

    }

메서드 내에서 Linq를 사용하여 DictionaryInfoConfigSection을 검색하고 일치하는 키로 값을 반환합니다. 하지만 다음 줄을 따라 구성 파일을 업데이트해야합니다.

<appSettings>
  <DirectoryMappings>
    <DirectoryMap key="MyBaseDir" value="C:\MyBase" />
    <DirectoryMap key="Dir1" value="[MyBaseDir]\Dir1"/>
    <DirectoryMap key="Dir2" value="[MyBaseDir]\Dir2"/>
  </DirectoryMappings>
</appSettings>

0

이 솔루션을 생각해 냈습니다.

  1. 응용 프로그램 Settings.settings에서 변수 ConfigurationBase를 정의했습니다 (type = string Scope = Application 포함).
  2. Settings.settings의 대상 속성에 변수를 도입했습니다. 모든 속성은 Scope = User로 설정해야합니다.
  3. app.xaml.cs에서 ConfigurationBase가
  4. app.xaml.cs에서 모든 변수를 ConfigurationBase 값으로 바꿨습니다. 런타임에 값을 바꾸려면 속성을 Scopr = User로 설정해야합니다.

모든 속성을 수동으로 변경해야하므로이 솔루션이 마음에 들지 않습니다. 새 속성을 추가하면 app.xaml.cs에서이를 고려해야합니다.

다음은 App.xaml.cs의 코드 조각입니다.

string configBase = Settings.Default.ConfigurationBase;
Settings.Default.CommonOutput_Directory = Settings.Default.CommonOutput_Directory.Replace("${ConfigurationBase}", configBase);

최신 정보

방금 개선 된 사항을 찾았습니다 (app.xaml.cs의 코드 스 니펫).

string configBase = Settings.Default.ConfigurationBase;

foreach (SettingsProperty settingsProperty in Settings.Default.Properties)
{
    if (!settingsProperty.IsReadOnly && settings.Default[settingsProperty.Name] is string)
    {
        Settings.Default[settingsProperty.Name] = ((string)Settings.Default[settingsProperty.Name]).Replace("${ConfigurationBase}", configBase);
    }
}

이제 Type = string 및 Scope = User가있는 내 설정의 모든 속성에 대해 대체가 작동합니다. 이런 식으로 좋아하는 것 같아요.

업데이트 2

속성을 통해 실행할 때 분명히 Scope = Application을 설정할 필요가 없습니다.


0

세 가지 가능한 솔루션

나는 내가 파티에 늦게 오는 것을 알고 있으며, 변수 구성 설정 문제에 대한 새로운 해결책이 있는지 찾고있었습니다. 내가 과거에 사용한 솔루션과 관련된 몇 가지 답변이 있지만 대부분은 약간 복잡해 보입니다. 같은 문제로 어려움을 겪는 사람들에게 도움이 될 수 있도록 이전 솔루션을 살펴보고 구현을 통합 할 것이라고 생각했습니다.

이 예에서는 콘솔 애플리케이션에서 다음 앱 설정을 사용했습니다.

<appSettings>
    <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
    <add key="StaticClassExample" value="bin"/>
    <add key="InterpollationExample" value="{0}bin"/>
  </appSettings>

1. 환경 변수 사용

나는 autocro autocro의 대답이 그것에 닿았 다고 생각 합니다. Visual Studio를 닫지 않고 빌드하거나 디버깅 할 때 충분한 구현을 수행하고 있습니다. 저는이 솔루션을 예전에 사용했습니다 ...

  • MSBuild 변수를 사용할 사전 빌드 이벤트 만들기

    경고 : 쉽게 대체되지 않는 변수를 사용하므로 프로젝트 이름 또는 변수 이름과 유사한 것을 사용하십시오.

    SETX BaseDir "$(ProjectDir)"

  • 변수 재설정; 다음과 같은 것을 사용합니다.

    스택 오버플로에서 환경 변수 새로 고침

  • 코드에서 설정을 사용하십시오.

'

private void Test_Environment_Variables()
{
    string BaseDir = ConfigurationManager.AppSettings["EnvironmentVariableExample"];
    string ExpandedPath = Environment.ExpandEnvironmentVariables(BaseDir).Replace("\"", ""); //The function addes a " at the end of the variable
    Console.WriteLine($"From within the C# Console Application {ExpandedPath}");
}

'

2. 문자열 보간을 사용합니다.

  • string.Format () 함수 사용

`

private void Test_Interpollation()
{
    string ConfigPath = ConfigurationManager.AppSettings["InterpollationExample"];
    string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
    string ExpandedPath = string.Format(ConfigPath, SolutionPath.ToString());
    Console.WriteLine($"Using old interpollation {ExpandedPath}");
}

`

3. 정적 클래스를 사용하여 이것이 제가 주로 사용하는 솔루션입니다.

  • 구현

`

private void Test_Static_Class()
{
    Console.WriteLine($"Using a static config class {Configuration.BinPath}");
}

`

  • 정적 클래스

`

static class Configuration
{
    public static string BinPath
    {
        get
        {
            string ConfigPath = ConfigurationManager.AppSettings["StaticClassExample"];
            string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
            return SolutionPath + ConfigPath;
        }
    }
}

`

프로젝트 코드 :

App.config :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
  <appSettings>
    <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
    <add key="StaticClassExample" value="bin"/>
    <add key="InterpollationExample" value="{0}bin"/>
  </appSettings>
</configuration>

Program.cs

using System;
using System.Configuration;
using System.IO;

namespace ConfigInterpollation
{
    class Program
    {
        static void Main(string[] args)
        {
            new Console_Tests().Run_Tests();
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }        
    }

    internal class Console_Tests
    {
        public void Run_Tests()
        {
            Test_Environment_Variables();
            Test_Interpollation();
            Test_Static_Class();
        }
        private void Test_Environment_Variables()
        {
            string ConfigPath = ConfigurationManager.AppSettings["EnvironmentVariableExample"];
            string ExpandedPath = Environment.ExpandEnvironmentVariables(ConfigPath).Replace("\"", "");
            Console.WriteLine($"Using environment variables {ExpandedPath}");
        }

        private void Test_Interpollation()
        {
            string ConfigPath = ConfigurationManager.AppSettings["InterpollationExample"];
            string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
            string ExpandedPath = string.Format(ConfigPath, SolutionPath.ToString());
            Console.WriteLine($"Using interpollation {ExpandedPath}");
        }

        private void Test_Static_Class()
        {
            Console.WriteLine($"Using a static config class {Configuration.BinPath}");
        }
    }

    static class Configuration
    {
        public static string BinPath
        {
            get
            {
                string ConfigPath = ConfigurationManager.AppSettings["StaticClassExample"];
                string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\"));
                return SolutionPath + ConfigPath;
            }
        }
    }
}

빌드 전 이벤트 :

프로젝트 설정-> 빌드 이벤트

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.