Question

I'm doing things considered horrible by some lately, but I personally enjoy this kind of experiment. Here's a telegraph style description:

  • Use NH to fetch data objects
  • Each DataObject is wrapped by a CastleDynamicProxy
  • When Properties decorated with Custom Attributes are queried, redirect to own code instead of NHibernate to get Returnvalue.

Object creation / data fetch code

Objects=GetAll().Select(x=>ProxyFactory.CreateProxy<T>(x)).ToList();

public IList<Person> GetAll()
{
    ISession session = SessionService.GetSession();
    IList<Person> personen = session.CreateCriteria(typeof(Person))
                          .List<Person>();
    return personen;
}

The Proxy generation Code:

public T CreateProxy<T>(T inputObject)
{
    T proxy = (T)_proxyGenerator.CreateClassProxy(typeof(T), new ObjectRelationInterceptor<T>(inputObject));
    return proxy;
}

The Interceptor used is defined like so:

    public class MyInterceptor<T> : IInterceptor
    {
        private readonly T _wrappedObject;

        public MyInterceptor(T wrappedObject)
        {
            _wrappedObject = wrappedObject;
        }

        public void Intercept(IInvocation invocation)
        {
            if (ShouldIntercept(invocation)) { /* Fetch Data from other source*/ }
            else
            {
                invocation.ReturnValue = invocation.Method.Invoke(_wrappedObject, invocation.Arguments);
            }
        }


        public bool ShouldIntercept(IInvocation invocation)
        {
            // true if Getter / Setter and Property
            // has a certain custom attribute
        }
    }

This works fine in an environment without NHibernate (creating objects in code, where the Object holds its own data). Unfortunately, the else part in the Intercept method seems to leave NHibernate unfunctional, it seems the _wrappedObject is reduced to it's base type functionality (instead of being proxied by NHibernate), so all mapped Child collections remain empty.

I tried switching from lazy to eager loading (and confirmed that all SQL gets executed), but that doesn't change anything at all.

Does anybody have an idea what I could do to get this back to work?

Thanks a lot in advance!

Was it helpful?

Solution

I found out that what I do is partially wrong and partially incomplete. Instead of deleting this question, I chose to answer it myself, so that others can benefit from it as well.

First of all, I have misunderstood the class proxy to be an instance proxy, which is why i stored the _wrappedObject. I needed the Object to perform invocation.Method.Invoke(_wrappedObject, invocation.Arguments), which is the next mistake. Instead of doing so, I should have passed the call on to the next interceptor by making use of invocation.Proceed().

Now, where was that Incomplete? NH seems to need to know Metadata about it's instances, so I missed one important line to make NH aware that the proxy is one of its kin:

SessionFactory.GetClassMetadata(entityName).SetIdentifier(instance, id, entityMode);

This only works in an NHibernate Interceptor, so the final product differs a bit from my initial one...Enough gibberish, you can see a very very comprehensible example on this on Ayende's website. Big props for his great tutorial!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top