どうもみむらです。
C# で ini ファイルを操作するとなると、
よくあるのが GetPrivateProfileString あたりを叩いて取得することになります。
でもその場合、いちいち要素を指定して取得しなければならず、
特に複数のキー(フィールド)がある場合に複数回コードを書くのも面倒です。
特に ini ファイルの項目が多くて、こんな状態になった日には・・。
・・ということで、 Reflection を使用して
この辺をすごく楽に出来るような感じでコードを書いてみました。
コード:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
public static class Ini
{
[DllImport("KERNEL32.DLL")]
public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName);
[DllImport("KERNEL32.DLL")]
public static extern uint GetPrivateProfileInt(string lpAppName, string lpKeyName, int nDefault, string lpFileName);
[DllImport("KERNEL32.DLL")]
public static extern uint WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);
public static T Read<T>(string section, string filepath)
{
T ret = (T)Activator.CreateInstance(typeof(T));
foreach (var n in typeof(T).GetFields())
{
if (n.FieldType == typeof(int))
{
n.SetValue(ret, (int)GetPrivateProfileInt(section, n.Name, 0, Path.GetFullPath(filepath)));
}
else if (n.FieldType == typeof(uint))
{
n.SetValue(ret, GetPrivateProfileInt(section, n.Name, 0, Path.GetFullPath(filepath)));
}
else
{
var sb = new StringBuilder(1024);
GetPrivateProfileString(section, n.Name, "", sb, (uint)sb.Capacity, Path.GetFullPath(filepath));
n.SetValue(ret, sb.ToString());
}
};
return ret;
}
public static void Write<T>(string secion, T data, string filepath)
{
foreach (var n in typeof(T).GetFields())
{
WritePrivateProfileString(secion, n.Name, n.GetValue(data).ToString(), Path.GetFullPath(filepath));
};
}
}
使い方:
ini ファイルの読み取りたいセクションに合わせたクラスを用意します。
public class Human
{
public string name;
public int age;
}
でもって次のような ini ファイルを用意して
あとはこんな風に呼び出します。
static void Main(string[] args)
{
var h = Ini.Read<Human>("01", "DATA.INI");
h.age = 15;
h.name = "JIRO";
Ini.Write("02", h, "DATA.INI");
}
実行しますと、
こんな感じでデータが読み出されます。
でもって、 ini ファイルは
[01]
name=TARO
age=20
[02]
name=JIRO
age=15
こんな感じに、ちゃんとセクション 02 が書き込まれます。
躓きそうなところ:
データを格納するクラスが、こういう感じに {get; set;} な状態になっている場合:
public class Human
{
public string name { get; set; }
public int age { get; set; }
}
上記コード内の GetFields を GetProperties に換え、 FieldType を PropertyType に変えれば動作します。
・・そんなわけで、もし良ければ自己責任でご利用ください-。