我正在解决一个问题,其中我有许多实体,每个实体都有一个对应的一对多翻译表,它指定实体字段的本地化版本。(所有这些都是我在其上添加地图的遗留模式)。例如:
- 事件
- ID
- 事件翻译
- 事件ID
- 语言
- 标题
- 其他领域
所以,如果我要用希腊语呈现我的信息,我会加入这两个表并指定 Language = 'Greek' 并拥有所有正确的东西。
我正在尝试做的是构建即时混合,将正确的数据直接合并到单个对象中,并将其作为查询结果返回,例如:
var someEvent = session.CreateCriteria<Event>().SetMaxResults(1).UniqueResult<IEvent>();
Console.WriteLine(someEvent.Title);
为此,我正在尝试设置一个 NHibernate 拦截器来创建 DynamicProxy mixins。除了它不起作用,我不知道为什么。这是设置,尽我所能简化它。
这是事件:
class Event : IEventEntity {
//ID and props here
public IList Translations {get; set;}
}
IEvenEntity
列表还有一个 getter 和 setter。还有一个EventTranslation
类,它超级简单,并且IEventTranslation
以最明显的方式实现。
Event的流畅地图:
class EventMap : ClassMap<Event>{
//obvious ID and properties stuff here...
HasMany<EventTranslation>(x => x.Translations);
}
单独工作正常——我可以查询事件并导航到他们的翻译。我很确定映射是好的。
我的拦截器形状基于 Krzysztof Koź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。有没有办法解决这个问题?
另外,就基本方法而言,在新罕布什尔州有更好的方法吗?