私は、エンティティのフィールドのローカライズされたバージョンを指定する、対応する1対多の変換テーブルをそれぞれに持つ多数のエンティティがあるという問題に取り組んでいます。(これはすべて、私が上にマップを追加しているレガシースキーマです)。例えば:
- イベント
- ID
- EventTranslation
- EventID
- 言語
- タイトル
- その他のフィールド
したがって、情報をギリシャ語でレンダリングする場合は、2つのテーブルを結合し、Language ='Greek'を指定して、すべての適切な情報を取得します。
私がやろうとしているのは、適切なデータを単一のオブジェクトに直接組み込み、クエリの結果としてそれを返すオンザフライミックスインを構築することです。
var someEvent = session.CreateCriteria<Event>().SetMaxResults(1).UniqueResult<IEvent>();
Console.WriteLine(someEvent.Title);
そのために、DynamicProxyミックスインを作成するためにNHibernateインターセプターをセットアップしようとしています。それが機能していないことを除いて、そして私は理由がわかりません。これがセットアップです。私がそれを単純化できる限り最善です。
イベントは次のとおりです。
class Event : IEventEntity {
//ID and props here
public IList Translations {get; set;}
}
IEvenEntity
リスト用のゲッターとセッターもあります。非常にシンプルで、可能な限り最も明白な方法でEventTranslation
実装されるクラスもあります。IEventTranslation
イベントの流暢なマップ:
class EventMap : ClassMap<Event>{
//obvious ID and properties stuff here...
HasMany<EventTranslation>(x => x.Translations);
}
それ自体で正常に動作します。イベントを照会して、その翻訳に移動できます。マッピングは良いと確信しています。
インターセプターの形は、KrzysztofKoźmicによる非常にクールなガイドに基づいており、少し関連性のあることを行っています。まず、動的プロキシを使用して実装するスーパーインターフェイスを作成しました。
public interface IEvent : IEventEntity, IEventTranslation{}
これが私のNHインターセプターです。明らかに、私は狂ったようにハッキングしています:
public class EventInterceptor : NHibernate.EmptyInterceptor
{
private readonly static ProxyGenerator gen = new ProxyGenerator();
public override object Instantiate(string clazz, NHibernate.EntityMode entityMode, object id)
{
var mixin = gen.CreateClassProxy(typeof(object), new[] { typeof(IEvent) }, new DynInterceptor());
//would also need to set the identifier here
return mixin;
}
}
DynInterceptorは、リレーションシップバッグに入り、適切な翻訳を取得し、適切な値を返す作業を実際に行うインターセプターです。詳細は呼び出されないため、あまり関連性がありません。
NHインターセプターを接続すると、実行されていることがわかります。実際、NHはキャストをIEvent
正しく取得します(つまり、プロキシは少なくとも作成されています)。しかし、何らかの理由で、それはエンティティの水分補給を完全に台無しにします:
Unhandled Exception: NHibernate.PropertyAccessException: could not set a property value by reflection setter of Event.Translations ---> System.Reflection.TargetException: Object does not match target type.
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisib
ilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, B
indingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, O
bject[] index)
at NHibernate.Properties.BasicPropertyAccessor.BasicSetter.Set(Object target,
Object value) in C:\thirdparty\NHibernate\src\NHibernate\Properties\BasicProper
tyAccessor.cs:line 304
NHがリフレクションを使用してプロパティを設定しているため、機能していないように見えますが、もちろん、IEventをEventに交換したため、ターゲットタイプが間違っています。これを回避する方法はありますか?
また、基本的なアプローチに関しては、NHでこれを行うためのより良い方法はありますか?