using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Reflection;
/// System.ComponentModel.DataAnnotations 는 참조에서 어셈블리를 추가해야 한다.
using
System.ComponentModel.DataAnnotations;
using
System.Runtime.InteropServices;
using
System.Text;
namespace
ConfigManager
{
/// <summary>
/// ini file의 정보를 담을 그릇(클래스)
/// <typeparam name="K1"></typeparam>
/// <typeparam name="K2"></typeparam>
/// <typeparam name="V"></typeparam>
[Serializable]
public
class
MultiKeyDictionary<k1, k2, v> : Dictionary<k1, dictionary<k2, v>>
{
public
V
this
[K1 key1, K2 key2]
{
get
{
if
(!ContainsKey(key1) || !
this
[key1].ContainsKey(key2))
{
return
default
(V);
}
return
base
[key1][key2];
}
set
{
if
(!ContainsKey(key1))
this
[key1] =
new
Dictionary<k2, v>();
this
[key1][key2] = value;
}
}
public
void
Add(K1 key1, K2 key2, V value)
{
if
(!ContainsKey(key1))
this
[key1] =
new
Dictionary<k2, v>();
this
[key1][key2] = value;
}
public
bool
ContainsKey(K1 key1, K2 key2)
{
return
base
.ContainsKey(key1) &&
this
[key1].ContainsKey(key2);
}
public
new
IEnumerable<v> Values
{
get
{
return
from baseDict
in
base
.Values
from baseKey
in
baseDict.Keys
select baseDict[baseKey];
}
}
}
/// <summary>
/// Section 구조
/// 추가할 Section이 있을 경우 enum에 추가하고 section name만 정의해주면 된다.
/// </summary>
public
enum
SectionNames
{
/// [Display(Name = "Database")] 에서 Name에 들어가는 문자열이 ini file에 실질적으로 쓰여지는 Section의 이름이다.
/// <summary>
/// Section Name "Database"
/// </summary>
[Display(Name =
"Database"
)]
Database_Section,
/// <summary>
/// Section Name "User"
/// </summary>
[Display(Name =
"User"
)]
User_Section,
}
/// <summary>
/// Database Section의 Key 나열
/// 추가할 key가 있을 경우 enum에 추가하고 디폴트 값만 정의해주면 된다.
/// </summary>
public
enum
Database_Section
{
/// [Display(Description = "localhost")]에서 Description에 들어가는 문자열은 ini에 key가 없는 경우 디폴트로 들어가는 값이다.
/// <summary>
/// Default Value : localhost
/// </summary>
[Display(Description =
"localhost"
)]
Address,
/// <summary>
/// Default Value : root
/// </summary>
[Display(Description =
"root"
)]
Id,
}
/// <summary>
/// User Section의 Key 나열
/// </summary>
public
enum
User_Section
{
/// <summary>
/// Default Value : 홍길동
/// </summary>
[Display(Description =
"홍길동"
)]
Name,
/// <summary>
/// Default Value : 29
/// </summary>
[Display(Description =
"29"
)]
Age,
}
public
class
ConfigData
{
private
string
inifilepath =
@"C:\Config.ini"
;
private
MultiKeyDictionary<sectionnames,
string
,
object
> _ConfigData =
null
;
[DllImport(
"kernel32.dll"
)]
private
static
extern
int
GetPrivateProfileString(
String section, String key, String def, StringBuilder retVal,
int
Size, String filePath);
[DllImport(
"kernel32.dll"
)]
private
static
extern
long
WritePrivateProfileString(
String Section, String key, String val, String filePath);
public
ConfigData()
{
_ConfigData =
new
MultiKeyDictionary<sectionnames,
string
,
object
>();
}
/// <summary>
/// ConfigData Class내에서 ini file을 쓰기 위한 함수
/// </summary>
/// <param name="Section">
/// <param name="Key">
/// <param name="Value">
private
void
IniWriteValue(String Section, String Key, String Value)
{
WritePrivateProfileString(Section, Key, Value, inifilepath);
}
/// <summary>
/// ConfigData Class내에서 ini file을 읽기 위한 함수
/// </summary>
/// <param name="Section">
/// <param name="Key">
/// <returns></returns>
private
String IniReadValue(String Section, String Key)
{
StringBuilder temp =
new
StringBuilder(255);
int
i = GetPrivateProfileString(Section, Key,
""
, temp, 255, inifilepath);
return
temp.ToString();
}
/// <summary>
/// 외부에서 ConfigData Class 객체를 이용해 Ini file의 값을 셋팅하기 위한 함수
/// </summary>
/// <typeparam name="KeyEnum"></typeparam>
/// <param name="key">
/// <param name="value">
public
void
SetConfigData<keyenum>(KeyEnum key,
string
value)
{
DisplayAttribute keyAttr =
typeof
(KeyEnum).GetMember(key.ToString())
.First()
.GetCustomAttribute<displayattribute>();
SectionNames sectionName = (SectionNames)Enum.Parse(
typeof
(SectionNames),
typeof
(KeyEnum).Name);
_ConfigData[sectionName][key.ToString()] = value;
}
/// <summary>
/// 외부에서 ConfigData Class 객체를 이용해 Ini file의 값을 가져오기 위한 함수
/// </summary>
/// <typeparam name="KeyEnum"></typeparam>
/// <param name="key">
/// <returns></returns>
public
string
getConfigData<keyenum>(KeyEnum key)
{
DisplayAttribute keyAttr =
typeof
(KeyEnum).GetMember(key.ToString())
.First()
.GetCustomAttribute<displayattribute>();
SectionNames sectionName = (SectionNames)Enum.Parse(
typeof
(SectionNames),
typeof
(KeyEnum).Name);
return
_ConfigData[sectionName][key.ToString()].ToString();
}
/// <summary>
/// Ini file을 저장하기 위한 함수
/// </summary>
public
void
SaveConfigData()
{
for
(
int
i = 0; i < _ConfigData.Count; i++)
{
for
(
int
j = 0; j < _ConfigData.ElementAt(i).Value.Count; j++)
{
string
sectionname = _ConfigData.ElementAt(i).Key.ToString();
DisplayAttribute keyAttr =
typeof
(SectionNames).GetMember(sectionname)
.First()
.GetCustomAttribute<displayattribute>();
string
section = keyAttr.Name;
string
key = _ConfigData.ElementAt(i).Value.ElementAt(j).Key.ToString();
string
value = _ConfigData.ElementAt(i).Value.ElementAt(j).Value.ToString();
IniWriteValue(
section,
key,
value
);
}
}
}
/// <summary>
/// Ini file을 읽기 위한 함수
/// </summary>
public
void
ReadConfigData()
{
foreach
(
string
strSectionName
in
Enum.GetNames(
typeof
(SectionNames)))
{
SectionNames sectionName = (SectionNames)Enum.Parse(
typeof
(SectionNames), strSectionName);
DisplayAttribute sectionAttr =
typeof
(SectionNames).GetMember(strSectionName)
.First()
.GetCustomAttribute<displayattribute>();
if
(!_ConfigData.ContainsKey(sectionName))
_ConfigData.Add(sectionName,
new
Dictionary<
string
,
object
=
""
>());
Type keyType = Type.GetType(
string
.Format(
"ConfigManager.{0}"
, sectionName));
foreach
(
string
strKeyName
in
Enum.GetNames(keyType))
{
DisplayAttribute keyAttr = keyType.GetMember(strKeyName)
.First()
.GetCustomAttribute<displayattribute>();
string
value = IniReadValue(sectionAttr.Name, strKeyName);
if
(!_ConfigData[sectionName].ContainsKey(strKeyName))
{
if
(!
string
.IsNullOrEmpty(value))
_ConfigData[sectionName].Add(strKeyName, value);
else
_ConfigData[sectionName].Add(strKeyName, keyAttr.Description);
}
else
{
if
(!
string
.IsNullOrEmpty(value))
_ConfigData[sectionName][strKeyName] = value;
else
_ConfigData[sectionName][strKeyName] = keyAttr.Description;
}
}
}
}
}
}
using
ConfigManager;
ConfigData _config =
new
ConfigData();
_config.ReadConfigData();
string
address = _config.getConfigData<database_section>(Database_Section.Address);
string
id = _config.getConfigData<database_section>(Database_Section.Id);
string
name = _config.getConfigData<user_section>(User_Section.Age);
string
age = _config.getConfigData<user_section>(User_Section.Name);
string
address_change =
"127.0.0.1"
;
string
id_change =
"server"
;
string
name_change =
"시나공공"
;
string
age_change =
"28"
;
_config.SetConfigData<database_section>(Database_Section.Address, address_change);
_config.SetConfigData<database_section>(Database_Section.Id, id_change);
_config.SetConfigData<User_Section>(User_Section.Name, name_change);
_config.SetConfigData<User_Section>(User_Section.Age, age_change);
_config.SaveConfigData();