2011-08-03 12 views
9

Zaczynam od MVC3 i chcę korzystać z elastycznej architektury, więc przeczytałem dziesiątki blogów, książkę (Pro ASP.NET MVC 3), przeczytałem o zasadach SOLID i wreszcie dostał się do struktury aplikacji lubię (a przynajmniej tak mi się wydaje, tak daleko, bo nie zbudowali niczego na nim jeszcze):Używanie programu Ninject w architekturze aplikacji SOLID

enter image description here

W tej strukturze:

  • Domain przechowuje klasy POCO i definiuje interfejsy usługi
  • Services realizuje interfejsów usług i określa repozytoria interfejsy
  • danych implementuje repozytoriów interfejsy
  • WebUI i domeny korzystania z usług
  • Usługi użyć repozytoriów
  • WebUI, usług i danych zależy od domeny dla klas POCO

Głównym powodem używania domeny przy użyciu usług jest sprawdzanie unikalnych kluczy w metodach Validate klas POCO (IValidatable).

Zaczynam budować aplikację odniesienia z tej struktury, ale mam do czynienia do tej pory dwa problemy:

  1. Używam projekt Data.Tests z testów jednostkowych dla repozytoriów, ale nie znalazłem sposobu na wstrzyknięcie (używając Ninject) implementacji usługi (w konstruktorze lub w inny sposób) na modelu, więc metoda sprawdzania poprawności może wywołać funkcję CheckUniqueKey w usłudze.

  2. Nie znalazłem żadnego odniesienia na temat podpinania projektu Ninject do projektu TEST (wiele projektów WebUI).

Co staram się osiągnąć tutaj jest w stanie przejść z EF na coś innego jak DAPPER, po prostu zmieniając zestaw danych.

UPDATE

Teraz (od 09-sie-2011) Ninject działa, ale myślę, że czegoś brakuje.

Mam CustomerRepository z dwóch konstruktorów:

public class CustomerRepository : BaseRepository<Customer>, ICustomerRepository 
{ 
    // The repository usually receives a DbContext 
    public CustomerRepository(RefAppContext context) 
     : base(context) 
    { 
    } 

    // If we don't receive a DbContext then we create the repository with a defaulte one 
    public CustomerRepository() 
     : base(RefApp.DbContext()) 
    { 
    } 

    ... 
} 

Na TestInitialize:

// These are for testing the Repository against a test database 

[TestInitialize()] 
public void TestInitialize() 
{ 
    // Context used for tests 
    this.context = new RefAppContext(); 

    // This is just to make sure Ninject is working, 
    // would have used: repository = new CustomerRepository(context); 

    this.kernel = NinjectMVC3.CreateKernel(); 

    this.kernel.Rebind<ICustomerRepository>().To<CustomerRepository>().WithConstructorArgument("context", context); 

    this.repository = kernel.Get<ICustomerRepository>(); 

} 

W klasie klientów:

public class Customer : IValidatableObject 
{ 
    ... 

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     // I want to replace this with a "magic" call to ninject 
     CustomerRepository rep = new CustomerRepository(); 

     Customer customer = rep.GetDupReferenceCustomer(this); 

     if (customer != null) 
      yield return new ValidationResult("Customer \"" + customer.Name + "\" has the same reference, can't duplicate", new [] { "Reference" }); 
    } 

    ... 
} 

Jaki byłby najlepszy sposób na wykorzystanie Ninject w tym scenariuszu?

Każda pomoc będzie bardzo ceniona.

ODPOWIEDŹ, coś

będę rozważać tę kwestię jako aswered tak daleko. Mogę sprawić, że Ninject będzie działał, ale wygląda na to, że osiągnięcie zasady Zanurzenia zależności (DIP) SOLID zajmie trochę więcej czasu.

Pod tym względem musiałem pogrupować domenę, usługi i dane, stworzę kolejne pytanie w innym czasie i utrzymam projekt na zwykły sposób.

Dziękuję wszystkim.

+1

Zasugeruj usunięcie odniesienia Ninject i zmień je na DI, ponieważ odpowiedź nie będzie (i nie powinna się zmieniać w zależności od konkretnego kontenera). Dodałbym również architekturę lub znajdę kilka dodatkowych tagów. –

+0

@Ruben masz rację, nie brzmi to całkiem poprawnie, aby użyć "Ninject" i "architektury aplikacji" na tym samym zdaniu, to właśnie w tym przypadku próbuję rozwiązać problem bardzo specyficzny dla Ninject. –

+1

Ułożyłem aktualizację na nowe pytanie, ponieważ jest to zupełnie inny temat, który nie ma wiele wspólnego z pierwszym. W przeciwnym razie niewiele osób przeczyta twój nowy problem. –

Odpowiedz

3

Jednostkowe testowanie powinno się odbywać bez Ninject. Po prostu stwórz instancję badanego obiektu i wstrzyknij próbkę dla każdej zależności ręcznie.

W przypadku testów integracyjnych można wykorzystać jądro zawierające wszystkie wiązania z aplikacji bootstrapper i ponownie powiązać wszystko, co chce się zastąpić makietą. na przykład Zastąp powiązanie sesji przez ten, który używa pamięci danych w pamięci zamiast prawdziwej bazy danych.

+0

W tej chwili robię testy integracyjne, ponieważ testuję repozytoria uzyskujące dostęp do rzeczywistej bazy danych. Użycie programu Ninject polega na tym, że można ostatecznie zastąpić warstwę usług czymś innym. W tym przypadku metoda POCO.Validate używa metody Service zdefiniowanej w interfejsie. Chodzi o to, np. jak rozwiązać interfejs usługi w Customer.Validate, aby móc skorzystać z metody CustomerServices.FindCustomerByEmail (e-mail), aby sprawdzić, czy istnieje inny klient z tym samym adresem e-mail. –

+0

@Miguel Veloso: Zaktualizowane testowanie integracyjne –

+0

Gdzie umieścić aplikację bootstrapper? W projekcie testowym nie ma Global.asax! –

Powiązane problemy