WPF에서 AppSettings Json 파일 사용하기

WPF에서 AppSettings Json 파일 사용하기

이철우

지난 .NET Framework는 App.config 파일을 사용하여 연결 문자열 및 로깅 공급자와 같은 앱에 대한 설정을 로드한다. 이제 .NET은 앱 설정에 appsettings.json 파일을 사용한다. appsettings.json에 대한 지원은 Microsoft.Extensions.Configuration NuGet 패키지에서 제공된다. 가능하면 과거의 App.config를 사용하지 않는 것이 좋다.[참고 1]

이 글은 .Net 9 WPF 프로젝트에서 appsettings.json 파일을 사용하는 방법을 보여준다.

닷넷 9 WPF 프로젝트(출력 형태를 'Console Application’으로 한다)를 만들고 NuGet 패키지 Microsoft.Extensions.Configuration 9.0.2과 Microsoft.Extensions.Configuration.Json 9.0.2를 설치한다.
솔루션 탐색기에서 방금 만든 프로젝트를 선택 - 우 클릭 - 추가(Add) - 클래스(Class) 선택하여 JavaScript JSON Configuration File 고르고, 파일 이름에 appsettings.json를 입력하고 추가(Add)를 누른다. 다음과 같이 appsettings.json 파일(속성-출력 디렉토리에 복사를 '항상 복사’로 선택한다 )이 생성되었다.

{
  "exclude": [
    "**/bin",
    "**/bower_components",
    "**/jspm_packages",
    "**/node_modules",
    "**/obj",
    "**/platforms"
  ]
}

그리고 App.xaml.cs 파일에

using Microsoft.Extensions.Configuration;

를 추가하고 다음과 같이 편집하자.

public partial class App : Application
{
    public static IConfiguration Config { get; private set; }

    public App()
    {
        Config = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .Build();
    }
}

MainWindow.xaml.cs를 다음과 같이 편집하자.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var section = App.Config.GetSection("exclude").AsEnumerable();

        foreach (var item in section)
        {
            Console.WriteLine($"{item}");
        }
    }
}

프로젝트를 실행하면 아래와 같다.

appsettings.json 파일을 조금 바꾸자.

{
  "exclude": [
    "**/bin",
    "**/bower_components",
    "**/jspm_packages",
    "**/node_modules",
    "**/obj",
    "**/platforms"
  ],

  "DataDirectory" : "D:\\Data"
}

MainWindow.xaml.cs도 조금 바꾸자.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var section = App.Config.GetSection("exclude").AsEnumerable();

        foreach (var item in section)
        {
            Console.WriteLine($"{item}");
        }

        Console.WriteLine();
        var dataDirectory = App.Config.GetSection("DataDirectory");
        Console.WriteLine($"Key:{dataDirectory.Key} Path:{dataDirectory.Path} Value:{dataDirectory.Value}");
    }
}

프로젝트를 실행하면 아래와 같다.

실제로 appsettings.json에 많은 App 관련 정보를 넣는 것보다는 간단하게 디렉토리 위치만 넣고 그 디렉토리 안에 파일을 참고하여 앱에 필요한 것을 얻는 것이 낫다고 생각한다. 물론 데이터베이스 접속 정보도 appsettings.json이 아니라 다른 파일에 넣어 appsettings.json에 있는 디렉토리에 저장하는 것이 좋을 것이다.

[참고 1] WPF 데스크톱 앱을 .NET 8로 업그레이드하는 방법

6개의 좋아요

'IConfiguration Config’가 정적 구성원이니 아래와 같이 바꿀 수 있습니다.

public partial class App : Application
{
    public static IConfiguration Config { get; }

    static App()
    {
        Config = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .Build();
    }
}

Generic Host를 사용하는 방법이 있을거 같은데요.

윈폼 샘플

2개의 좋아요

오늘 마침 이거 관련해서 해가지고…
복습 할 겸 기록을 남겨보도록하겠습니다.

사용하기 앞서 필요한 라이브러리

Install-Package Microsoft.Extensions.Configuration
Install-Package Microsoft.Extensions.Configuration.Json
Install-Package Microsoft.Extensions.Configuration.Binder
  1. *.Configuration 의 역할
  • IConfiguration, ConfigurationBuilder 등의 핵심 인터페이스와 클래스가 없음
  1. *.Configuration.Json의 역할
  • AddJsonFile("appsettings.json")을 사용할 때 JSON을 로드하는 기능이 없음
  1. *.Configuration.Binder의 역할
  • config.GetSection("ApplicationSettings").Bind(settings); 같은 코드에서 Bind()가 없음

샘플코드

{
   "ConnectionStrings": {
    "DefaultConnection": "Server=127.0.0.1;Database=test;User Id=test;Password=test1234!;TrustServerCertificate=True;"
  },
}
// 설정
var builder = new ConfigurationBuilder ()
    .SetBasePath (Directory.GetCurrentDirectory ()) // 현재 실행 경로 기준
    .AddJsonFile ("appsettings.json", optional: true, reloadOnChange: true);
// optional => false로 설정하면 파일이 없을 경우 예외 발생, true이면 파일이없어도 무시하고 계속 실행
// reloadOnChange => false로 설정하면, 파일이 바뀌어도 애플리케이션이 재시작되기 전까지 변경 사항이 반영되지 않습니다. true로 설정하면, JSON 파일이 수정될 때 자동으로 다시 로드됩니다.
 var services = new ServiceCollection ();

services.AddSingleton<IConfiguration> (builder.Build ());
services.AddSingleton<MainWindow> ();
public MainWindow(IConfiguration config)
{
   var defaultConnectionString = config.GetConnectionString("DefaultConnection");  // or config["ConnectionStrings:DefaultConnection"];

   Console.WriteLine(defaultConnectionString);
   /*
   output:
   Server=127.0.0.1;Database=test;User Id=test;Password=test1234!;TrustServerCertificate=True;
   */
}

참고
GetConnectionString() 의 경우


확장메서드로 제공된 기능입니다.

1개의 좋아요

좋은 댓글 고맙습니다.

아래 [// 설정] 부문은 전체 코드 중 어디에 있는 것인지요?


1개의 좋아요

개발자마다 성향이 매우달라서 자세히 적진않았습니다.
저같은 경우에는 app.xaml.cs에
OnStartup 을 오버라이드해서 넣었습니다.

1개의 좋아요

저는 [ServiceLocator] 사용하지 않습니다.

Is ServiceLocator an anti-pattern?

1개의 좋아요

서비스 로케이터는 2010년부터 안티패턴인데요.

오버라이드를 서비스 로케이터라고 말씀 하신건가요?

2개의 좋아요

아, 제가 'ServiceCollection’을 그렇게 - ServiceLocator - 라고 생각했습니다.
그래도 ServiceCollection 사용하지 않습니다.

참고 글 - The ServiceCollection Extension Pattern - 에는 ServiceCollection을 사용하라고 나와 있습니다.

1개의 좋아요

저도 사용하진않고있어요…!
ioc를 통해 의존성 주입을 할뿐입니다…!

2개의 좋아요

아니요 :slight_smile:

예시

Ioc.Default.ConfigureServices (services.BuildServiceProvider ());
        this.MainWindow = new MainWindow
        {
            DataContext = Ioc.Default.GetService<MainViewModel> ()
        };

이렇게 작성 하고있어요!

2개의 좋아요

이런 글도 있습니다.

DI는 IoC를 사용하지 않아도 된다

https://jwchung.github.io/DI는-IoC를-사용하지-않아도-된다

1개의 좋아요

DI와 IOC관련해서는 한참 이야기 해야 하는데요. 한번 불탄 주제라서…

쓰레드 주제와는 무관한듯합니다.

3개의 좋아요

네~ 옆길로 갔습니다. 주제가. ㅋ

1개의 좋아요