4

I'm using Unity to resolve types dynamically for a pluggable architecture. I'm also using interception to apply business rule validation via AOP (using ValidationAspects). Finally, I'm using NHibernate as an ORM to persist domain objects.

In order for AOP to work, we use the VirtualMethodInterceptor, as interface interception doesn't work with NHibernate. I have a facade over ISession that handles casting between interface and real types for repository operations.

To make sure that all objects in the graph fetched via NHibernate are properly proxied for AOP, I made an NH IInterceptor implementation and overrode the Instantiate() method, so I could supply NH with created objects rather than have it call new(). I then use Container.Resolve() to get back proxied objects with the validation injected, and give this back to NH to populate. This works OK.

The problem comes when the session flush occurs. NHibernate gets upset because the objects it sees in the graph are of the proxy type rather than the real type. The way we're mapping (all via property, all virtual) NH should be able to get all the values it needs via the proxy, if I could override the type-checking.

What I need to know is: given a transparently proxied object created by Unity with Interception enabled, is there a) any way to obtain a direct reference to the 'real' instance it's proxying, or b) to override NH and tell it to treat objects of a proxy type as if it were of a known mapped type, dynamically at runtime?

Neil Hewitt
  • 2,518
  • 18
  • 24
  • Could you build a basic test-case of this? Have you considered using NHibernate.Validator instead of this? (http://nhforge.org/wikis/validator10/nhibernate-validator-1-0-0-documentation.aspx) – Mauricio Scheffer Feb 24 '09 at 22:30
  • I hadn't, though I may look at it a little more since you mention it. We like ValidationAspects specifically because of the AOP capability - you can do method or parameter-level validation without needing to call any helper methods at all. – Neil Hewitt Feb 24 '09 at 23:48
  • Even a simple test-case is likely to run to a lot of LOCs. I know what the 'problem' is - it's a clash between the NH view of the world and the Unity Interceptor view. In theory Castle Windsor + PostSharp would work, but I like Unity and would like to make a go of it. May have to hack source :-( – Neil Hewitt Feb 24 '09 at 23:50
  • well nhibernate.validator registers through event listeners, so you don't need to call any helper methods – Mauricio Scheffer Feb 25 '09 at 00:14
  • Thanks, I'll look more closely. – Neil Hewitt Feb 25 '09 at 13:50
  • I've voted to close this one because I went down another route and I don't think an answer would be generically helpful to others... – Neil Hewitt Feb 27 '09 at 00:07

1 Answers1

0

We use interception for caching. So in our class, that implements ICallHandler we have code like this:

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        //...
        var nextHandler = getNext();

        var realReturn = nextHandler(input, getNext);

        var cacheRefreshingItemParameters = new CacheRefreshingItemParameters
        {
            InterfaceMethod = input.MethodBase,
            InterfaceType = input.MethodBase.DeclaringType,
            TargetType = input.Target.GetType() //remember original type
        };
        _cacheProvider.Add(cacheKey, realReturn.ReturnValue, cacheRefreshingItemParameters);

        //...
        return (cachedReturn);
    }

We put cacheRefreshingItemParameters in cache UpdateCallback and then resolve original service:

var service = _unityContainer.Resolve(parameters.TargetType);
Backs
  • 24,430
  • 5
  • 58
  • 85