私はNHibernate 3.3を使用しており、次のようにリフレクションを介してクラス階層をDBにマップしようとしています:
class Parent
{
public virtual IList<Child> Children { get; set; }
}
class Child
{
public virtual Parent MyParent { get; set; }
}
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Helper.Map(this);
}
}
public class Helper
{
public static void Map<T>(ClassMap<T> map)
{
foreach (var property in typeof(T).GetProperties())
{
// creating lambda x => x.Children
var arg = Expression.Parameter(typeof(T), "x");
Expression expr = Expression.Property(arg, property);
// Func<Parent, IList<Child>> does not work in HasMany()
// var type = typeof(Func<,>).MakeGenericType(typeof(T), property.PropertyType);
// but IEnumerable works
var type = property.PropertyType.GetGenericArguments()[0]; // Child
type = typeof(IEnumerable<>).MakeGenericType(type); // IEnumerable<Child>
type = typeof(Func<,>).MakeGenericType(typeof(T), type); // Func<Parent, IEnumerable<Child>>
dynamic lambda = Expression.Lambda(type, expr, arg);
map.HasMany(lambda);
}
}
}
上記は単純化された例にすぎません。主なアイデアは、すべてのコレクション プロパティに対して HasMany() を動的に呼び出すことです。それを行うためのより直接的な方法を見つけることはできないようですが、うまくいきます。
問題は、Cascade.All() をマップに適用すると、StackOverflow 例外が発生することです。マッピングが手動で行われる場合、これは問題なく機能するため、マッピングミスの問題になる可能性は低くなります。