2012-11-17 20 views
6

Zgubiłem się z Ninject w WPF.Aplikacja WPF z Ninject

Inicjuję go w App.xaml, ale właściwość ITest w MainWindow.xaml (nawet z InjectAttribute) nie jest rozwiązywana i pozostaje pusta.

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    {  
     IKernel kernel = new StandardKernel(); 
     kernel.Bind<ITest, Test>(); 
     base.OnStartup(e); 
    } 
} 

I googled nieco i okazało się, że to nie działa w ten sposób. Próbując znaleźć rozwiązanie, doszedłem do stworzenia IMainWindow z niczym więcej niż "void Show();" i dodanie go do MainWindow.

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    {  
     IKernel kernel = new StandardKernel(); 
     kernel.Bind<ITest, Test>(); 

     kernel.Bind<IMainWindow, MySolution.MainWindow>(); 
     kernel.Get<IMainWindow>().Show(); 

     base.OnStartup(e); 
    } 
} 

Do tego dostaję NullReferenceException na linii z .get

Próbowałem też tak:

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    {  
     IKernel kernel = new StandardKernel(); 
     kernel.Bind<ITest, Test>(); 

     MainWindow = new MySolution.MainWindow(kernel); 
     //then kernel.Inject(this); in the MainWindow constructor 
     MainWindow.Show(); 

     base.OnStartup(e); 
    } 
} 

Teraz dostaję NullReferenceException na linii .Inject w MainWindow.

Znalazłem różne rozwiązania, ale wydawało mi się, że są w wadze ciężkiej i zrezygnowałem z testowania ich wszystkich i próbowałem, który z nich działa.

Proszę o pomoc?

+0

Co dokładnie to 'NullReferenceException' jest? – AgentFire

Odpowiedz

5

Nie rejestrujesz poprawnie swoich typów, dlatego drugi przykład rzuca wykonanie. Poprawna składnia jest następująca: kernel.Bind<SomeInterface>().To<SomeImplementation>()

więc prawidłowe użytkowanie:

protected override void OnStartup(StartupEventArgs e) 
{ 
    IKernel kernel = new StandardKernel(); 
    kernel.Bind<ITest>().To<Test>(); 

    kernel.Bind<IMainWindow>().To<MainWindow>(); 
    var mainWindow = kernel.Get<IMainWindow>(); 
    mainWindow.Show(); 

    base.OnStartup(e); 
} 

A trzeba zaznaczyć swoją właściwość z atrybutem [Inject]:

public partial class MainWindow : Window, IMainWindow 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    [Inject] 
    public ITest Test { get; set; } 
} 

public interface IMainWindow 
{ 
    void Show(); 
} 
+0

Huh, myślałem, że Bind () jest taki sam jak Bind (). Do (). Najwyraźniej nie. Dzięki! – Mirek

+0

Nie za pomocą 'Bind ()' możesz powiązać dwa interfejsy z jedną implementacją, ale nadal musisz dostarczyć implementację '.To <>'. – nemesv

+0

Wiem, że to jest stare, ale kiedy to zrobię, otrzymuję dwa główne okna, w przeciwieństwie do jednego. jakieś pomysły? – JMK

0

Jestem pewien, że masz rozwiązanie, ale możesz użyć zastrzyku konstruktora zamiast wtrysku właściwości na MainWindow, jeśli chcesz.

Dzięki temu unika się tworzenia fałszywego interfejsu IMainWindow i tworzenia niepotrzebnych właściwości publicznych dla wszystkich wstrzykniętych klas.

Oto rozwiązanie:

MainWindow.cs

public partial class MainWindow : Window, IMainWindow 
{ 
    private readonly ITest test; 

    public MainWindow(ITest test) 
    { 
     this.test = test; 
     InitializeComponent(); 
    } 

} 

App.xaml.cs:

protected override void OnStartup(StartupEventArgs e) 
{ 
    IKernel kernel = new StandardKernel(); 
    kernel.Bind<ITest>().To<Test>(); 

    var mainWindow = kernel.Get<MainWindow>(); 
    mainWindow.Show(); 

    base.OnStartup(e); 
}