ASP.NET MVC5 vs Ninject

0

Cześć, przerabiam aktualnie temat z wstrzykiwaniem danych - zgodnie z książką Zaawansowane programowanie w ASP.NET MVC5 (fragment rozdziału poświęcony ninject). Postanowiłem przełożyć przykład książki na własny. Ale podczas uruchamiania otrzymuje pewny błąd (opiszę to na końcu, wrzucę obecnie co posiadam):
Inteface:

public interface IUser
    {/// <summary>
    /// Metoda dodaje uzytkownika do DB
    /// </summary>
    /// <param name="user">Obiekt uzytkownika</param>
        void AddUser(Users user);
        /// <summary>
        /// Metoda usuwa uzytkownika z DB
        /// </summary>
        /// <param name="user">Obiekt uzytkownika</param>
        void DeleteUser(Users user);
        /// <summary>
        /// Metoda zwraca uzytkownika po loginie
        /// </summary>
        /// <param name="login">Login uzytkownika</param>
        /// <returns>Obiekt uzytkownika</returns>
        Users ReturnUserByLogin(string login);
        /// <summary>
        /// Metoda zwraca uzytkownika po adresie Mail
        /// </summary>
        /// <param name="mail">Adres Mail do ktorego jest przypisane konto</param>
        /// <returns>Obiekt uzytkownika</returns>
        Users ReturnUserByMail(string mail);
        /// <summary>
        /// Metoda aktualizuja uzytkownika o zadanym ID
        /// </summary>
        /// <param name="oldUser">Uzytkownik, dla ktorego maja zostac zaktualizowane dane</param>
        /// <param name="newUser">Wartosci ktore maja zostac nadpisane</param>
        void UpdateUser(Users oldUser, Users newUser);
        /// <summary>
        /// Metoda sprawdza czy podany login jest juz wykorzystywany w DB
        /// </summary>
        /// <param name="login">Login uzytkownika</param>
        /// <returns>True/False - istnieje/nie istnieje</returns>
        bool IsLoginExist(string login);
        /// <summary>
        /// Metoda sprawdza czy podany mail jest juz zarejestrowany w DB
        /// </summary>
        /// <param name="mail">Adres mail</param>
        /// <returns>True/False - istnieje / nie istnieje</returns>
        bool IsMailExist(string mail);
      
    }

Klasa implementująca w/w interfejs:

 class UserHelper : IUser
    {
        private Model contextDB = new Model();
        private IUser user;
       public UserHelper(IUser userParam)
        {
            user = userParam;
        }
        public void AddUser(Users user)
        {   
            contextDB.Users.Add(user);
            contextDB.SaveChanges();
        }

        public void DeleteUser(Users user)
        {
            contextDB.Users.Remove(user);
            contextDB.SaveChanges();
        }

        public bool IsLoginExist(string login)
        {
            return contextDB.Users.Any(x => x.Login == login);

        }

        public bool IsMailExist(string mail)
        {
            return contextDB.Users.Any(x => x.AdressMail == mail);
        }

        public Users ReturnUserByLogin(string login)
        {
            Users user = new Users();
            user = (Users)(from x in contextDB.Users where x.Login == login select x);
            return user;
        }

        public Users ReturnUserByMail(string mail)
        {
            Users user = new Users();
            user = (Users)(from x in contextDB.Users where x.AdressMail == mail select x);
            return user;
        }

        public void UpdateUser(Users oldUser, Users newUser)
        {
            Users user = new Users();
            user = (Users)(from x in contextDB.Users where x.UserID == oldUser.UserID select x);
            if(user != null)
            {
                user.AdressMail = newUser.AdressMail;
                user.IsActivated = newUser.IsActivated;
                user.Login = newUser.Login;
                user.Password = newUser.Password;
                contextDB.Users.Remove(oldUser);
                contextDB.Users.Add(user);
            }

        }
    }

Bindowanie wykonałem zgodnie z książką : kernel.Bind<IUser>().To<UserHelper>();

Teraz, chcę wykorzystać działanie mechanizmu w "praktyce". W domyślnym kontrolerze Home dodałem konstruktor :

private IUser _iuser;
public HomeController(IUser userParam)
        {
            _iuser = userParam;
        }

Teraz po odpaleniu solucji dostanę błąd:
"Error activating IUser using binding from IUser to UserHelper
A cyclical dependency was detected between the constructors of two services.". Wychodzi na to, że nie może zbindować interfejsu i klasy UserHelper. Ktoś byłby w stanie pomóc rozwiązać w/w problem, oraz pokazać na w/w klasach jak praktycznie wykorzystać tutaj ninject?

Z góry dzięki za wszelkie odpowiedzi.
Jeśli ktoś napisze, że bezsensu jest wykorzystanie w tym przykładzie Ninject'a (to uprzedzam, po prostu chcę poznać tą technologię - i głównie o to mi chodzi)

2

W konstruktorze klasy UserHelper, wstrzykujesz IUser. IUser zgodnie z tym co zarejestrowałeś w kontenerze DI podmienia Ci na ..... UserHelper. Do kontrolera powinieneś wstrzykiwać ten IUser (a faktycznie UserHelper), a nie do konstruktora UserHelper.

0

Czyli w klasie UserHelper utworzyć zwykły bezparametrowy konstruktor. Natomiast w kontrolerze Home (zostawić konstruktor taki jak jest)?

0

Nie jest Ci nawet potrzebny ten konstruktor w UserHelper. A kontroler zostaw tak jak jest.
Ale twój kod wymaga więcej zmian.
Powinieneś mieć klasę User, a nie Users. A gdy potrzebujesz zwracać więcej niż jeden użytkownik to zwracaj ich listę.
Mieszasz query syntax i method syntax. Przywyknij do pisania w method syntax, jest czytelniejsze i bardziej powszechne. W query syntax nie da się chyba zrobić wszystkiego.
Przemyśl sprawę dbContext. Ja disposuje context po każdym użyciu - tworze go za pomocą instrukcji using wtedy kiedy go potrzebuje.

1
kzkzg napisał(a):

Przemyśl sprawę dbContext. Ja disposuje context po każdym użyciu - tworze go za pomocą instrukcji using wtedy kiedy go potrzebuje.

To teraz pytanie czy jesteś w stanie przetestować metodę która ma taki using z DBContextem?.
Moim zdaniem lepiej wstrzykiwać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1