Получение реального экземпляра от прокси под Unity Interception с NHibernate - PullRequest
4 голосов
/ 24 февраля 2009

Я использую Unity для динамического разрешения типов для подключаемой архитектуры. Я также использую перехват для применения проверки бизнес-правил через AOP (с использованием ValidationAspect ). Наконец, я использую NHibernate в качестве ORM для сохранения объектов домена.

Чтобы AOP работал, мы используем VirtualMethodInterceptor, поскольку перехват интерфейса не работает с NHibernate. У меня есть фасад над ISession, который обрабатывает приведение между интерфейсом и реальными типами для операций с репозиторием.

Чтобы убедиться, что все объекты в графе, выбранном через NHibernate, правильно проксированы для AOP, я сделал реализацию NH IInterceptor и переопределил метод Instantiate(), чтобы я мог предоставить NH созданным объектам, а не вызывать его new(). Затем я использую Container.Resolve(), чтобы получить обратно прокси-объекты с введенной проверкой, и возвращаю это NH для заполнения. Это работает хорошо.

Проблема возникает, когда происходит сброс сеанса. NHibernate расстроен, потому что объекты, которые он видит на графике, имеют тип прокси, а не реальный тип. То, как мы отображаем (все через свойство, все виртуальное), NH должен иметь возможность получить все необходимые значения через прокси, если бы я мог отменить проверку типов.

Что мне нужно знать, так это: с учетом прозрачно проксируемого объекта, созданного Unity с включенным перехватом, есть ли: а) любой способ получить прямую ссылку на «реальный» экземпляр, который он проксирует, или б) отменить NH и сообщить это обрабатывать объекты прокси-типа, как если бы он был известного отображаемого типа, динамически во время выполнения?

1 Ответ

0 голосов
/ 13 августа 2015

Мы используем перехват для кэширования. Итак, в нашем классе, который реализует ICallHandler, у нас есть такой код:

    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);
    }

Мы помещаем cacheRefreshingItemParameters в кэш UpdateCallback и затем разрешаем исходный сервис:

var service = _unityContainer.Resolve(parameters.TargetType);
...