使用NHibernate拦截器和DynamicProxy混合边表数据

使用NHibernate拦截器和DynamicProxy混合边表数据,nhibernate,castle-dynamicproxy,dynamic-proxy,Nhibernate,Castle Dynamicproxy,Dynamic Proxy,我正在解决一个问题,其中有许多实体,每个实体都有一个对应的一对多翻译表,该表指定实体字段的本地化版本。(所有这些都是我在上面添加映射的遗留模式)。例如: 事件 身份证 事件翻译 事件 语言 头衔 其他领域 因此,如果我要用希腊语呈现我的信息,我将连接两个表,并指定Language='Greek',并具有所有正确的内容 我试图做的是动态构建mixin,将正确的数据直接合并到单个对象中,并作为查询结果返回,如: var someEvent = session.CreateCriteria

我正在解决一个问题,其中有许多实体,每个实体都有一个对应的一对多翻译表,该表指定实体字段的本地化版本。(所有这些都是我在上面添加映射的遗留模式)。例如:

  • 事件
    • 身份证
  • 事件翻译
    • 事件
    • 语言
    • 头衔
    • 其他领域
因此,如果我要用希腊语呈现我的信息,我将连接两个表,并指定Language='Greek',并具有所有正确的内容

我试图做的是动态构建mixin,将正确的数据直接合并到单个对象中,并作为查询结果返回,如:

var someEvent = session.CreateCriteria<Event>().SetMaxResults(1).UniqueResult<IEvent>();
Console.WriteLine(someEvent.Title);
IEvenEntity
还有一个列表的getter和setter。还有一个
EventTranslation
类,它非常简单,以最明显的方式实现
ieventtransation

活动的流畅地图:

class EventMap : ClassMap<Event>{
  //obvious ID and properties stuff here...
  HasMany<EventTranslation>(x => x.Translations);
}
这是我的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中是否有更好的方法来实现这一点?

我不确定,但我认为您应该将过滤器与eventlistener结合使用,以获得您想要的结果。如果在语言表上设置筛选器,并在要启用筛选的事件之前使用eventlistener启用筛选器,则可能会获得所需的行为。

我不确定,但我认为应该将筛选器与eventlistener结合使用,以获得所需的结果。如果您在语言表上设置了一个过滤器,并在要启用过滤的事件之前使用eventlistener启用过滤器,您可能会获得所需的行为。

好的,那么对于我提出的这个问题有多复杂,结果是非常简单的,如果我知道的足够多,我本可以像您一样提出这个问题“如何动态地使对象实现另一个接口而不丢失其类型?”。答案是提供一个目标,如中所示

Type type = Type.GetType(clazz, false);
var mixin = (Event)gen.CreateClassProxy(type, new[] { typeof(IEvent) }, new DynInterceptor());

好的,我提出这个问题有多复杂,结果很简单,如果我知道的足够多,我可以问这样一个问题:“我如何动态地使一个对象实现另一个接口而不丢失它的类型?”。答案是提供一个目标,如

Type type = Type.GetType(clazz, false);
var mixin = (Event)gen.CreateClassProxy(type, new[] { typeof(IEvent) }, new DynInterceptor());
Type type = Type.GetType(clazz, false);
var mixin = (Event)gen.CreateClassProxy(type, new[] { typeof(IEvent) }, new DynInterceptor());