Я работаю над проблемой, в которой у меня есть несколько сущностей, у каждой из которых есть соответствующая таблица переводов «один ко многим», которые указывают локализованные версии полей сущностей. (все это устаревшая схема, над которой я добавляю карту). Например:
- Event
- 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?