Смешивание данных боковых таблиц с помощью перехватчиков NHibernate и DynamicProxy - PullRequest
1 голос
/ 14 июня 2011

Я работаю над проблемой, в которой у меня есть несколько сущностей, у каждой из которых есть соответствующая таблица переводов «один ко многим», которые указывают локализованные версии полей сущностей. (все это устаревшая схема, над которой я добавляю карту). Например:

  • Event
    • ID
  • EventTranslation
    • EventID
    • Язык
    • Название
    • другие поля

Итак, если бы я собирался представить свою информацию на греческом языке, я бы присоединился к двум таблицам и указал Language = 'Greek' и получил все нужные данные.

То, что я пытаюсь сделать, - это создавать миксины «на лету», которые напрямую объединяют нужные данные в единый объект и возвращают их в результате запросов, например:

var someEvent = session.CreateCriteria<Event>().SetMaxResults(1).UniqueResult<IEvent>();
Console.WriteLine(someEvent.Title);

Для этого я пытаюсь настроить перехватчик NHibernate для создания миксинов DynamicProxy. За исключением того, что это не работает, и я не знаю почему. Вот установка, как можно лучше упростить ее.

Вот событие:

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);
}

Сам по себе работает нормально - я могу запрашивать события и переходить к их переводам. Я уверен, что отображение хорошее.

Я основал форму моего материала-перехватчика на очень крутом путеводителе Кшиштофа Кошича за то, что он сделал что-то немного связанное. Сначала я создал суперинтерфейс, который собираюсь реализовать с помощью динамического прокси:

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 на Событие. Есть ли способ обойти это?

Кроме того, что касается базового подхода, есть ли лучший способ сделать это в NH?

Ответы [ 2 ]

1 голос
/ 27 июня 2011

ОК, так как я усложнил этот вопрос, он оказался довольно простым, и если бы я знал достаточно, я мог бы задать вопрос: «Как мне динамически заставить объект реализовать другой интерфейс, не теряяего тип?Ответ заключается в предоставлении цели, как в

Type type = Type.GetType(clazz, false);
var mixin = (Event)gen.CreateClassProxy(type, new[] { typeof(IEvent) }, new DynInterceptor());
0 голосов
/ 24 июня 2011

Я не уверен, но я думаю, что вы должны использовать фильтр в сочетании с обработчиком событий, чтобы получить желаемый результат. Если вы установите фильтр в своей языковой таблице и используете список событий, чтобы включить фильтр до событий, для которых вы хотите включить фильтрацию, вы можете получить желаемое поведение.

...