2016-08-11 14 views
0

Ich habe das folgende Szenario Export-Plugins für meine Anwendung für die Erklärung:Mit Konstruktorargumente mit 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 (Assembly) scheint nicht RealPlugin als ladbares Element und die Last zu erfassen () Methode wird nie aufgerufen. Es funktioniert, wenn ich einen zusätzlichen öffentlichen Konstruktor ohne Argumente für beide Klassen hinzufüge. Das möchte ich aber eigentlich nicht, weil ich nicht möchte, dass jemand eine Instanz von RealPlugin erstellt, ohne die Datenquelle anzugeben.

Ein hässlicher Workaround scheint zu sein, die parameterlosen Konstruktoren mit [Obsolete] zu markieren, was zumindest verhindert, dass sie versehentlich verwendet werden.

Natürlich könnte ich auch separate Klassen erstellen, die von NinjectModule abgeleitet sind, um die Bindungen zu erstellen, aber das erfordert eine andere Klasse für jedes meiner Plugins, was auch nicht so schön ist (und verhindert die Bindung an den dynamischen Typ der Instanz), wie oben zu sehen)

Jeder hat eine Idee, wie ein solches Plugin registriert werden kann, ohne einen öffentlichen parameterlosen Konstruktor zu haben?

+0

Ich bin mir ziemlich sicher, dass ninject keine Unterstützung für Modulkonstruktoren bietet. Wenn ein Modul also einen ctor-Parameter benötigt, muss man es selbst neu erstellen und stattdessen mit 'Kernel.Load (NinjectModule)' laden mit 'Kernel.Load (AssemblyName)'. – BatteryBackupUnit

+0

Siehe auch http://stackoverflow.com/questions/8022062/how-to-inject-an-object-into-a-ninject-module – BatteryBackupUnit

+0

@BatteryBackupUnit: Es ist mir egal, etwas in das Modul injizieren, ich nur don Ich möchte keinen öffentlichen Konstruktor erstellen. Ich würde mich freuen, wenn es auch mit geschützten oder privaten Konstrukteuren arbeiten würde. – PMF

Antwort

0

In Reflection werden standardmäßig nur "öffentliche" Typen berücksichtigt. Anscheinend verwendet Ninject die Standardwerte. So werden Sie haben Ihre eigene Implementierung rollen, die Reflexion nutzt alle Klassen zu finden, die alle diese Kriterien entsprechen:

  • von NinjectModule vererben (auch indirekt)
  • nicht abstrakt
  • hat einen Parameter-less Erbauer

dann müssen diese instanziiert werden und an Kernel.Load(NinjectModule) weitergeleitet werden.

Sie könnten genauso gut den Quellcode von Kernel.Load(AssemblyName) betrachten und ihn nach Ihren Bedürfnissen kopieren und ändern. Höchstwahrscheinlich erfordert der Code, der die Reflexion nutzt, nur eine false, die an einer oder zwei Stellen auf eine true geschaltet wird - oder eine andere Methodenüberladung verwendet, die auch nicht-öffentliche Mitglieder berücksichtigt.

+0

Ja, natürlich könnte ich das tun, aber das wollte ich vermeiden. Ich hatte bereits eine eigene Implementierung für das Laden von Modulen auf Reflektionsbasis implementiert und ich habe sie jetzt durch Ninject ersetzt (weil sie bereits an anderer Stelle in unserer Codebasis verwendet wird), so dass ich das Rad jetzt nicht wirklich neu erfinden möchte. – PMF

+0

LOL, dann hättest du das vielleicht an erster Stelle gesagt ;-). Sie könnten auch versuchen, eine Pull-Anfrage an Ninject zu stellen ... – BatteryBackupUnit

+0

Vielleicht werde ich das in der Tat versuchen. Ich habe gehört, dass sie sehr restriktiv sind, wenn sie Änderungen akzeptieren. – PMF

Verwandte Themen