ActiveRecord.netを作ってみたよ

――まあタイトルは釣りで、「作りかけてみたよ」ってなもんですがね。.net2.0のジェネリクスとリフレクションを駆使してRuby on RailsActiveRecord風にORマッピングするというもくろみ。
元ネタは生産性を向上させるメタオブジェクト技術 - 分裂勘違い君劇場 by ふろむだ

class Person : ActiveRecord<Person> {
    public string name;
    public int age;
}

これだけ定義してやれば、

Person hoge=Person.FindFirst("name","hoge hoge");
hoge.age=50;
hoge.Save();

ってな感じにRails風味なことが可能。あとクラス定義からテーブルを生成したりもできる。
リレーション関係の機能が未実装なのでまだ役立たずだけど、Windows環境で手軽なDBアプリ作るのには向いてるんじゃないかと。


現時点でのサンプルコードはこんな感じ:

namespace Sandbox {
    class Person : ActiveRecord<Person> {
        public string name;
        public int age;
    }
    class Program {
        static DBConnector db;
        static void Main(string[] args) {
            ActiveRecordBase.EstablishConnection("test.db", "New=True");
            db = Person.DB;

            db.DropTableIfExists("persons");
            Person.CreateTable(); //Personのクラス定義からテーブルを生成する
            
            add("dilbert", 30);
            add("alice", 29);
            add("wally", 32);
            add("pointy-haired", 50);
            DispAll();

            Console.WriteLine();
            Console.WriteLine("add asok");
            Person newbie = new Person();
            newbie.name = "asok";
            newbie.age = 25;
            newbie.Save();
            DispAll();

            Console.WriteLine();
            Console.WriteLine("delete alice");
            Person alice = Person.FindFirst("age", 29);
            alice.Destroy();
            DispAll();
        }
        private static void DispAll() {
            Console.WriteLine("==== all members =====");
            foreach(Person p in Person.FindAll())
                Console.WriteLine("{0} ({1})", p.name, p.age);
        }
        static void add(string name, int age) {
            //データ型関係がちょっとアレ
            db.Insert("persons", "name", "\"" + name + "\"", "age", "\"" + age.ToString() + "\"");
        }
    }
}


/* output:
==== all members =====
dilbert (30)
alice (29)
wally (32)
pointy-haired (50)

add asok
==== all members =====
dilbert (30)
alice (29)
wally (32)
pointy-haired (50)
asok (25)

delete alice
==== all members =====
dilbert (30)
wally (32)
pointy-haired (50)
asok (25)
 */


リレーション関係はこんな感じになる予定:

public class Person : ActiveRecord<Person> {
    public string name;
    public int age;
    public belongs_to<Company> company;
}
public class Company : ActiveRecord<Company> {
    public string name;
    public has_many<Person> workers;
}

Person.FindFirst("name","hoge").company.Get().name;
Company.FindFirst("name","hoge co.,ltd.").workers.Count;

Get()のくだりがちょっとださいが、仕方なしかも。カラム名とかの設定はカスタム属性でごにゃごにゃ。