2016-08-11 6 views
0

Я следующий сценарий для объявления экспорта плагинов для моего приложения:Используя аргументы конструктора с NinjectModule

public abstract class PluginBase : NinjectModule 
{ 
    protected PluginBase(IDataSource source) 
    { 
     // ... 
    } 

    public override void Load() 
    { 
     Bind<PluginBase>().To(GetType()); 
    } 
} 
public class RealPlugin : PluginBase 
{ 
    public RealPlugin(IDataSource source) 
    { 
     // ... 
    } 
} 

Unfortunatelly, Kernel.Load (AssemblyName), кажется, не обнаружить RealPlugin, как загружаемый элемент и Load () метод никогда не вызывается. Он работает, если я добавляю дополнительный публичный конструктор без аргументов для обоих классов. Тем не менее, я на самом деле не хочу этого делать, потому что я не хочу, чтобы кто-либо создавал экземпляр RealPlugin без указания источника данных.

Уродливое обходное решение похоже на маркировку конструкторов без параметров [Устаревшее], что, по крайней мере, предотвращает их случайное использование.

Конечно, я мог бы также создавать отдельные классы, происходящие из NinjectModule, для создания привязок, но для каждого из моих плагинов требуется еще один класс, что также не так хорошо (и предотвращает привязку к динамическому типу экземпляра, как видно выше)

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

+0

Я уверен, что ninject не поддерживает впрыскивание чего-либо в конструкторы модулей, поэтому, если для модуля требуется параметр ctor, вам всегда нужно будет его самостоятельно создать и загрузить его с помощью 'Kernel.Load (NinjectModule)' вместо использования 'Kernel.Load (AssemblyName)'. – BatteryBackupUnit

+0

Также см. Http://stackoverflow.com/questions/8022062/how-to-inject-an-object-into-a-ninject-module – BatteryBackupUnit

+0

@BatteryBackupUnit: Мне все равно, что вы вводите что-либо в модуль, я просто Не хочу создавать публичный конструктор. Я был бы рад, если бы он работал с защищенными или частными конструкторами. – PMF

ответ

0

В Reflection по умолчанию рассматриваются только «общедоступные» типы. По-видимому, ninject использует значения по умолчанию. Так что вам придется свернуть свою собственную реализацию, которая использует отражение найти все классы, которые соответствуют всем этим критериям:

  • унаследовав от NinjectModule (косвенно)
  • не абстрактный
  • имеет параметр меньше конструктор

тогда они должны быть увековечены и переданы по адресу Kernel.Load(NinjectModule).

Вы также можете ознакомиться с исходным кодом Kernel.Load(AssemblyName) и скопировать и изменить его в соответствии с вашими потребностями. Скорее всего, код, использующий отражение, просто потребует, чтобы false переключился на true в одном или двух местах - или используя другую перегрузку метода, которая также рассматривает непубличных членов.

+0

Да, конечно, я мог бы это сделать, но этого я и хотел избежать. Раньше у меня была собственная реализация для загрузки на основе рефлексивного модуля, и теперь я заменил ее на Ninject (потому что он уже используется в другом месте в нашей кодовой базе), поэтому мне не очень нравится изобретать колесо сейчас. – PMF

+0

LOL, тогда, может быть, вы должны были сказать это в первую очередь ;-). Вы также можете попробовать предоставить запрос на удаление для ninject ... – BatteryBackupUnit

+0

Возможно, я попытаюсь это сделать. Я слышал, что они очень ограничивают принятие изменений. – PMF