保留与NH会话不相关的Castle DynamicProxy [英] Persisting a Castle DynamicProxy that's not associated with a NH Session

查看:109
本文介绍了保留与NH会话不相关的Castle DynamicProxy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的会话使用NHInterceptor向模型添加INotifyPropertyChanged支持.

My session uses an NHInterceptor to add INotifyPropertyChanged support to models.

// I use the session generated here to fetch Data
public class SessionServiceImpl : ISessionService
{
    [Inject]
    public ISessionFactory SessionFactory { get; set; }

    [Inject]
    public NhChangeNotificationInterceptorImpl ChangeNotificationInterceptor { get; set; }

    public ISession GetSession() // reduced code here
    {
        return SessionFactory.OpenSession(ChangeNotificationInterceptor);
    }
}

// This is the interceptor implementation
public class NhChangeNotificationInterceptorImpl : EmptyInterceptor, IInterceptor
{
    [Inject]
    public ISessionFactory SessionFactory { get; set; }

    [Inject]
    public ViewModelProxyFactory ProxyFactory { get; set; }

    public override object Instantiate(string entityTypeName, EntityMode entityMode, object id)
    {
        Type type = Type.GetType(entityTypeName); 

        if (type == null) { /* Throw Exception*/ }
        bool isViewModel = false;
        while (type != typeof(object))
        {
            Type tempType = type.BaseType;
            if (tempType == typeof(ViewModelBase))
            {
                isViewModel = true;
                break;
            }
        }

        if (entityMode == EntityMode.Poco && isViewModel)
        {
            var instance = ProxyFactory.CreateProxy(type);
            SessionFactory.GetClassMetadata(entityTypeName).SetIdentifier(instance, id, entityMode);
            return instance;
        }
        return base.Instantiate(entityTypeName, entityMode, id);
    }
}

ProxyFactory使用Castle创建可添加更改通知功能的代理.这意味着所有我的对象都来自数据库,作为城堡代理,它们是AFAIK透明的.

The ProxyFactory uses Castle to create proxies that add change notification functionality. That means all my objects come from the DB as Castle Proxies, which are AFAIK transparent.

每当我将这些NH生成的MVVM代理之一传递给Session.Save()时,一切都很好.

Whenever I pass one of those NH Generated MVVM-proxies into Session.Save(), all's fine.

现在,随着数据驱动的应用程序的发展,我还需要创建新实例并保存它们.我可以创建模型类型的实例,然后通过会话保存它们.创建MVVM代理实例(使用Ninject确保整个使用相同的SessionFactory和ProxyFactory实例)并将其扔到Session.Save()中将导致以下结果:

Now, as data driven Applications go, I also need to create new instances and save them. I can create instances of the model type and save them via the session all right. Creating a MVVM proxy instance (using Ninject to ensure that the same SessionFactory and ProxyFactory instances are used all over) and throwing this into Session.Save() results in the following:

"NHibernate.MappingException".
  Message=No persister for: Castle.Proxies.FieldDescriptionProxy
  Source=NHibernate
  StackTrace:
       at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String entityName)
       at NHibernate.Impl.SessionImpl.GetEntityPersister(String entityName, Object obj)
       at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
       at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
       at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
       at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
       at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
       at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
       at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
       at NHibernate.Impl.SessionImpl.Save(Object obj)
       at Interpretation.UI.Service.Impl.Dao.FieldDao.SaveFields(IList`1 fields, ISession session) in C:\...\FieldDao.cs:Zeile 51.
  InnerException: 


有什么想法在这里出了什么问题(或者我可能忘记了什么)?


Any ideas what goes wrong here (or what I might have forgotten)?

现在可以正常工作了,但是为什么必须在外部创建的实例的拦截器中添加识别逻辑(请参见下面的代码),而在内部创建的实例却可以原样保留呢?

EDIT : Now got it working, but why do I have to add recognition logic (see code below) to the interceptor for instances created outside, while instances created inside can be persisted as the are?

    public override string GetEntityName(object entity)
    {
        Type type = entity.GetType();
        if (type.FullName.StartsWith("Castle.Proxies") &&
            type.FullName.EndsWith("Proxy"))
        {
            return type.BaseType.FullName;
        }
        return base.GetEntityName(entity);
    }

推荐答案

实现GetEntityName方法可以解决问题.

Implementing the GetEntityName method did the trick.

public override string GetEntityName(object entity)
{
    Type type = entity.GetType();
    if (type.FullName.StartsWith("Castle.Proxies") &&
        type.FullName.EndsWith("Proxy"))
    {
        return type.BaseType.FullName;
    }
    return base.GetEntityName(entity);
}

这篇关于保留与NH会话不相关的Castle DynamicProxy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆