Глядя на код генерации прокси: https://github.com/ninject/ninject.extensions.interception/blob/master/src/Ninject.Extensions.Interception.DynamicProxy/DynamicProxyProxyFactory.cs
if (targetType.IsInterface)
{
reference.Instance = this.generator.CreateInterfaceProxyWithoutTarget(targetType, additionalInterfaces, InterfaceProxyOptions, wrapper);
}
else
{
object[] parameters = context.Parameters.OfType<ConstructorArgument>()
.Select(parameter => parameter.GetValue(context, null))
.ToArray();
reference.Instance = this.generator.CreateClassProxy(targetType, additionalInterfaces, ProxyOptions, parameters, wrapper);
}
можно видеть, что расширение динамического прокси ninject передает генератору динамических прокси Castle только ConstructorArgument
s.
Итак, без изменений в расширении ninject или создания собственного — вам нужно передать все зависимости в качестве аргументов конструктора. Вы также можете проверить, работает ли внедрение свойств/методов (см. https://github.com/ninject/ninject/wiki/Injection-Patterns).
Если вы контролируете код, вы можете добавить интерфейсы к прокси-классам, а затем использовать "прокси интерфейса с целью". Это позволяет отделить создание прокси-сервера от создания экземпляра целевого (прокси-класса) --> цель может иметь зависимости ctor, внедренные без каких-либо изменений в ninject (-extensions).
Пояснение: наличие следующего класса, который следует проксировать:
public interface IBar { }
public class Foo
{
public Foo(IBar bar)
{
}
}
И следующая привязка:
Bind<Foo>().ToSelf().Intercept().With<SomeInterceptor>();
Bind<IBar>().To<Bar>();
А затем извлечение Foo
из контейнера ninject:
IResolutionRoot.Get<Foo>();
не будет работать.
Помещение всех аргументов конструктора в контекст нинекта, чтобы заставить его работать
Однако мы можем изменить получение Foo
, чтобы оно заработало:
var bar = IResolutionRoot.Get<IBar>();
IResolutionRoot.Get<Foo>(new ConstructorArgument("bar", bar);
Теперь это неоптимально, потому что ninject не выполняет автоматическое разрешение зависимостей.
Добавление интерфейса в прокси-класс, чтобы он работал лучше
Мы можем обойти эту проблему, используя «интерфейсный прокси с целью». Во-первых, мы добавляем интерфейс к проксируемому классу:
public interface IFoo{ }
public class Foo : IFoo
{
public Foo(IBar bar)
{
}
}
И затем мы меняем привязку на:
Bind<IFoo>().To<Foo>().Intercept().With<SomeInterceptor>();
А затем извлечение Foo
из контейнера ninject:
IResolutionRoot.Get<Foo>();
работает.
Еще одно, возможно, более простое (и более уродливое?) решение Согласно @Daniel, это работает: добавьте два конструктора к прокси-типу:
- один конструктор
protected
без параметров. Это для DynamicProxy для создания прокси.
- один конструктор
public
/internal
с аргументами, который будет использоваться ninject для создания экземпляра прокси-типа.
Ninject автоматически выберет конструктор с наибольшим количеством аргументов, которые он может разрешить.
person
BatteryBackupUnit
schedule
12.03.2014
IPlanningStrategy
или просто.Intercept().With<SomeInterceptor>()
? - person BatteryBackupUnit   schedule 12.03.2014InterceptorAttribute
), а затем использую собственный класс стратегии планирования, чтобы пройти через классы и проверить методы, которые имеют атрибуты, а затем проксировать их. Обновлю основной вопрос примером. - person Grofit   schedule 12.03.2014