2013-10-13 2 views
1

Я пытаюсь понять, как Ninject.Extensions.Interception 3.0.0.8 создает динамические прокси для моих классов. Я обнаружил, что когда я украшаю свои конкретные классы атрибутом, который наследуется от InterceptAttribute или когда я напрямую перехватываю время привязки с помощью метода Intercept(), тогда Ninject возвращает динамический прокси украшенного класса вместо обычного типа.Почему Ninject Bind with Interception возвращает прокси-сервер?

У меня есть IPolicySearchPresenter интерфейса, который я привязка к конкретному типу FlexPolicySearchPresenter добавления Exception регистратора перехватчика:

Bind<IExceptionInterceptor>().To<ExceptionInterceptor>(); 
Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>(); 

Проблема заключается в том, что, когда я инспектировать возвращающийся тип для этого связывания:

var proxy = Kernel.Get<IPolicySearchPresenter>(); 

Я получаю экземпляр Castle.Proxies.IPolicySearchPresenterProxy вместо FlexPolicySearchPresenterProxy

Это дает мне проблемы с моим приложением для удаления FluorineFx. Тем не менее, если я создаю мой замок прокси вручную:

ProxyGenerator generator = new ProxyGenerator(); 
    //My presenter type 
    Type type = typeof(FlexPolicySearchPresenter); 
    //My presenter interface 
    var interfaceType = type.GetInterfaces().Single(); 
    //Get my Interceptor from container. Notice that i had to 
    //change my Interceptor to implement IInterceptor from Castle libs, 
    // instead of Ninject IInterceptor 
    var excepInt = Kernel.Get<ExceptionInterceptor>(); 
    //Manually get all my instances required by my presenter type Constructor 
    //ideally passed through Constructor Injection 
    var presenterSearchService = Kernel.Get<IPolicySearchService>(); 
    var userAuthService = Kernel.Get<IUserAuthorizationService>(); 
    //Create proxy, passing interceptor(s) and constructor arguments 
    var proxy = generator.CreateClassProxy(type, new object[] { presenterSearchService, userAuthService }, 
      new IInterceptor[] 
     { 
      excepInt 
     }); 
    //Ninject.Extensions.Interception.DynamicProxyModule 
    // I'm using directive ToConstant(..), and not To(..) 
    //Bind my interface to the new proxy 
    Bind(interfaceType).ToConstant(proxy).InThreadScope(); 

var proxy = Kernel.Get<IPolicySearchPresenter>(); 

Возвращающиеся типы возвращаются в Castle.Proxies.FlexPolicySearchPresenterProxy, который прекрасно работает с моей реализации удаленного взаимодействия.

Вопрос в том, как я могу получить Ninject.Interception вернуть мне экземпляры FlexPolicySearchPresenterProxy вместо IPolicySearchPresenterProxy. Обратите внимание, что, делая ручной замок, как я связывающую иначе:

 Bind(interfaceType).ToConstant(proxy).InThreadScope(); 

Вместо Ninject образом:

Bind<IPolicySearchPresenter>().To<FlexPolicySearchPresenter>().Intercept().With<IExceptionInterceptor>(); 

мне нужно сделать, чтобы изменить способ, которым я делаю Binding в Ninject, чтобы получить правильный тип?

+0

Вы пытались создать привязку с IPolicy .. к FlexPolicy * и *, а затем привязку FlexPolicy .ToSelf() .Intercept(). С ...? (Sidenote: перехватчики ninject instanciaties один раз для каждого типа, а не один экземпляр прокси). – BatteryBackupUnit

+0

Нет, я не пробовал. Я попробую сегодня утром. Спасибо за предложение –

+0

Я сделал это: 'Bind (). ();' 'Bind (). ToSelf(). Intercept(). С ();' 'var proxy = Kernel.Get ();' Но прокси возвращается как «FlexPolicySearchPresenter», а не «FlexPolicySearchPresenterProxy», а перехват не пинает :( –

ответ

1

Редактировать: добавлена ​​функция впрыска в Foo.

У меня есть рабочее решение для вас, но, честно говоря, я не на 100% доволен этим. Во всяком случае, это работает:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var kernel = new StandardKernel(); 
     kernel.Bind<IFoo>().ToMethod(ctx => ctx.Kernel.Get<Foo>()); 

     kernel.Bind<Foo>().ToSelf().Intercept().With<SomeInterceptor>(); 

     var foo = kernel.Get<IFoo>(); 

     foo.DoSomething(); 

     Console.WriteLine(foo.GetType()); 

     Console.Read(); 
    } 
} 

public interface IFoo 
{ 
    void DoSomething(); 
} 

public class Foo : IFoo 
{ 
    [Inject] 
    public Bar Dependency { get; set; } 

    public virtual void DoSomething() 
    { 
     Console.WriteLine("doing something with {0}", this.Dependency); 
    } 
} 

public class SomeInterceptor : IInterceptor 
{ 
    public SomeInterceptor() 
    { 
     Console.WriteLine("interceptor created"); 
    } 

    public void Intercept(IInvocation invocation) 
    { 
     Console.WriteLine("before"); 
     invocation.Proceed(); 
     Console.WriteLine("after"); 
    } 
} 

public class Bar 
{ 
    public override string ToString() 
    { 
     return "Bar (injected dependency)"; 
    } 
} 

Полученный результат:

interceptor created 
before 
doing something with Bar (injected dependency) 
after 

И тип:

Castle.Proxies.FooProxy 

кажется, что .bind() К() и. .Bind(). ToSelf(). Перехват ... не имеет такого же результата. Я не знаю, почему (пока), но, возможно, я собираюсь расследовать это.

Update на аргументы конструктора: Ninject сам по себе поддерживает только «наследование класса на основе прокси» - где класс нуждается в/пустой CTOR по умолчанию и «интерфейс прокси без цели» - которая является то, что вы не хотите.

Следовательно, было бы приемлемым для вас использовать инъекцию свойств «только этот раз»? В противном случае вам нужно будет создать собственный перехват ninject-magic и использовать «прокси-сервер класса с целью» (см. http://docs.castleproject.org/Tools.Kinds-of-proxy-objects.ashx) Примечание: Несмотря на то, что «прокси-сервер класса с целью» поддерживает аргументы конструктора, вам нужно знать, какие они есть заранее (поэтому нет легкой поддержки DI). (Я не нашел крючок для разрешения аргументов конструктора после того, как динамический прокси выбирает/создает конструктор для прокси.)

+0

Я попробую, как только моя Visual Studio вернется к жизни. Спасибо за вашу помощь! –

+0

Не работал для меня. Я получаю эту ошибку: «Не удалось найти конструктор без параметров». Мой FlexPolicySearchPresenter является немного более сложным, имеет внедрение конструктора: 'общественного FlexPolicySearchPresenter (IPolicySearchService policySearchServiceService, IUserAuthorizationService iUserAuthorizationService) : основание (iUserAuthorizationService) { _policySearchService = policySearchServiceService; } ' –

+0

Да это происходит из Castle.DynamicProxy: в Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance (тип proxyType, List'1 proxyArguments, тип classToProxy, Object [] constructorArguments) в Castle.DynamicProxy.ProxyGenerator.CreateClassProxy (тип classToProxy, Тип [] дополнительныеИнтерфейсыToProxy, параметры ProxyGenerationOptions, Object [] constructorArguments, IInterceptor [] перехватчики) в Castle.DynamicProxy.ProxyGenerator.CreateClassProxy (тип classToProxy, параметры ProxyGenerationOptions, Object [] constructorArguments, IInterceptor [] перехватчики) –

Смежные вопросы