1

私は、エンティティのフィールドのローカライズされたバージョンを指定する、対応する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でこれを行うためのより良い方法はありますか?

4

2 に答える 2

1

さて、私がその質問をどれほど複雑にしたかについては、それは非常に単純であることがわかりました。十分に知っていれば、「オブジェクトにタイプを失うことなく動的に別のインターフェイスを実装させるにはどうすればよいですか?」という質問をすることができました。 "。答えは、次のようにターゲットを提供することです

Type type = Type.GetType(clazz, false);
var mixin = (Event)gen.CreateClassProxy(type, new[] { typeof(IEvent) }, new DynInterceptor());
于 2011-06-27T18:07:17.860 に答える
0

よくわかりませんが、希望する結果を得るには、フィルターをイベントリスナーと組み合わせて使用​​する必要があると思います。言語テーブルにフィルターを設定し、イベントリスナーを使用して、フィルタリングを有効にするイベントの前にフィルターを有効にすると、目的の動作が得られる場合があります。

于 2011-06-24T06:35:19.530 に答える