Кто расскажет про то как работает ninject, а именно аттрибут [inject] - вопрос №1072536

Ответы

Ninject так же прост в изучении, как и Autofac. А благодаря множеству отдельных библиотек использование Ninjectпредоставляет все доступные на сегодняшний день возможности для управления зависимостями. В своей основе Ninjectочень прост для того, чтобы, потратив минимальный отрезок времени, его можно было использовать в Enterprise decision (бизнес-решениях). Хотя он не поддерживает interception, конфигурирования через xml(для этого нужно скачивать отдельно библиотеки, которых на момент написания статьи было около 30),asp.newmvc, MVC3, NLog, Glimpse и т.д. Чтобы продемонстрировать, как использовать данный IoCконтейнер, рассмотрим ту же реализацию электронной библиотеки, которая была использована для рассмотрения предыдущих IoCконтейнеров в предыдущих статьях (Unity, Autofac, CastleWindsorи StructureMap). Диаграмма классов приведена ниже.изображение из вопросаДля того, чтобы показать, как использовать контейнер Ninject, удалим в App.xamlстрочку для запуска формы в DependencyProperty(DP) -StartupUri. Для инициализации IoCконтейнера перед стартом программы необходимо перейти в классы App.xaml.csи переопределить метод OnStartup. Затем необходимо написать соответствующую реализацию.protectedoverridevoidOnStartup(StartupEventArgse){    varkernel = newStandardKernel();    kernel.Bind<IBook>().To<LibraryBook>();    kernel.Bind<ILibraryBookService>().To<LibraryBookService>();    kernel.Bind<IVisitorRepository>().To<VisitorRepository>();    kernel.Bind<MainViewModel>().ToSelf();    kernel.Bind<MainWindow>().ToSelf();    varmodel = kernel.Get<MainViewModel>();    varview = kernel.Get<MainWindow>();    view.DataContext = model;    view.Show();}Для простых программ достаточно всего две инструкции:Bind().To(); Bind().ToSelf(); Но для более сложных можно использовать дополнительные методы по выбору lifetimemanager(менеджер жизни объектов), инициализацию и использование конструктора на выбор, methodinjection(MI) и propertyinjection(PI) и многое другое. Ninjectтакже хорош тем, что он позволяет выполнять конфигурации в отдельных модулях. Посмотрим, насколько упростится наш пример с использованием модулей (NinjectModule). publicclassLibraryModule: NinjectModule{    publicoverridevoidLoad()    {        Bind<IBook>().To<LibraryBook>();        Bind<ILibraryBookService>().To<LibraryBookService>();        Bind<IVisitorRepository>().To<VisitorRepository>();        Bind<MainViewModel>().ToSelf();        Bind<MainWindow>().ToSelf();    }}Использование данного модуля:varkernel = newStandardKernel(newLibraryModule());varmodel = kernel.Get<MainViewModel>();varview = kernel.Get<MainWindow>();view.DataContext = model;view.Show();К сожалению, базового функционала, который идет в IoCконтейнере Ninject, может быть недостаточно для Вашего приложения, поэтому нужно будет загружать необходимые дополнения. Ninjectспроектирован по принципу: базовый функционал плюс дополнительные возможности, которые можно установить отдельно. Например, если Вы сторонник NHibernateи конфигурирования через файл конфигурации и не знакомы со Spring.Net(он отлично подходит для настроек NHibernate), посмотрите в сторону данного IoCконтейнера. Пример с NHibernateбыл просто приведен для сравнения, чтобы показать, как дополнительные библиотеки Ninjectпозволят ускорить процесс разработки. ConstrainResolutionОчень часто при разработке программного обеспечения приходится сталкиваться с тем, что от одного интерфейса наследуется несколько классов. А класс, который использует данный интерфейс, должен знать, с каким из вышеперечисленных вариантов его нужно использовать. Одним из самых простых вариантов решения данной проблемы является именованная привязка (Namedbinding). Продемонстрируем именованную привязку в электронной библиотеке, которая использовалась для примеров, добавив класс, который будет отвечать за работу с домашней коллекцией книг. Назовем этот класс HomeLibraryBookService, который наследуем от интерфейса ILibraryBookService. Ниже будет приведена тестовая реализация для демонстрации использования данного класса. В списке источников в конце статьи Вы можете скачать исходные коды к данной статье и ознакомится более подробно с использованием Ninject.publicclassHomeLibraryBookService: ILibraryBookService{    #regionVariable    privateObservableCollection<IBook> _books;    #endregion     #regionConstructor    publicHomeLibraryBookService()    {        _books = newObservableCollection<IBook>();        _books.Add(newLibraryBook{ Author = «Test1», Title = «Test Unity1», Count = 3, SN = «ISBN: 9781617291340», Year = newDateTime(2013, 9, 10) });        _books.Add(newLibraryBook{ Author = «Test2», Title = «Test Unity2», Count = 2, SN = «ISBN-10: 0201485672», Year = newDateTime(1999, 7, 8) });    }    #endregion     #regionPublic Methods    publicvoidGetData(Action<ObservableCollection<IBook>, Exception> callback)    {        callback(_books, null);    }     publicIBookFindBook(IBookfindBook)    {        if(findBook == null)            returnnull;         return_books.FirstOrDefault(book => book.Author == findBook.Author                                    && book.Title == findBook.Title                                    && book.SN == findBook.SN                                    && book.Year == findBook.Year);    }     publicvoidCreateNewBook()    {        _books.Add(newLibraryBook{ Author = «UnityTest1», Title = «Test1», Count = 5, SN = «ISBN-10: 0735667454», Year = DateTime.Now });    }     publicvoidRemoveBook(IBookbook)    {        if(book == null)            return;         _books.Remove(book);    }    #endregion}Интерфейс ILibraryBookServiceиспользуется в модели представления MainViewModel,которая отвечает за связывание моделей с представлением для проекта “Электронная библиотека”. Реализация представлена ниже. publicclassMainViewModel: NotifyModelBase    {        privatereadonlyILibraryBookService_libraryDataService;         publicMainViewModel(ILibraryBookServicedataService)        {            _libraryDataService = dataService;            _libraryDataService.GetData(                (items, error) =>                {                    Books = items;                });        }}С данного класса для был приведен только необходимый код для модифицированного примера использования. Посмотрим, как изменился класс LibraryModuleсо внесением именованной привязки.publicclassLibraryModule: NinjectModule{    publicoverridevoidLoad()    {        Bind<IBook>().To<LibraryBook>();        Bind<ILibraryBookService>().To<HomeLibraryBookService>().Named(«HomeLibrary»);        Bind<ILibraryBookService>().To<LibraryBookService>().Named(«Library»);        Bind<IVisitorRepository>().To<VisitorRepository>();        Bind<MainViewModel>().ToSelf();        Bind<MainWindow>().ToSelf();    }}К сожалению, сразу после внесения проект не запустится, так как нужно указать, какой класс будет использоваться при constructorinjectionв классе MainViewModel. Поэтому в данном классе изменим немного вызов конструктора.publicMainViewModel([Named(«Library»)]ILibraryBookServicedataService)В данном примере был рассмотрен один из самых простых способов решения ограничения по привязке. Другим способом является ограничения связывания с помощью использования ConstraintAttribute. Поскольку в примере с электронной библиотекой сложно представить, как использовать данный подход, возьмем пример, предоставленный разработчиками  Ninject.// will work just as well without this line, but it's more correct and important for IntelliSense etc.[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,    AllowMultiple = true, Inherited = true)]publicclassSwimmer: ConstraintAttribute{    publicboolMatches(IBindingMetadatametadata)    {        returnmetadata.Has(«CanSwim») && metadata.Get<bool>(«CanSwim»);    }}classWarriorsModule: Ninject.Modules.NinjectModule{    publicoverridevoidLoad()    {        Bind<IWarrior>().To<Ninja>();        Bind<IWarrior>().To<Samurai>().WithMetadata(«CanSwim», false);        Bind<IWarrior>().To<SpecialNinja>().WithMetadata(«CanSwim», true);    }}classAmphibiousAttack{    publicAmphibiousAttack([Swimmer]IWarrior warrior)    {        Assert.IsType<SpecialNinja>(warrior);    }} ИтогиNinject-это мощный и одновременно легкий в использовании IoCконтейнер. По простоте использования, а также понятности apiэтот контейнер чем-то напоминает Autofac. Данный контейнер имеет очень мощную поддержку в онлайн-обществе. Пожалуй, единственным нюансом, который может смущать в данном IoCконтейнере, -это скорость его работы. Почему-то этот контейнер для управления зависимостями уступает по скорости всем описанным мной ранее IoCконтейнерам. Но если у Вас небольшое приложение, и Вам не нужно создавать много объектов через данный контейнер, то в плане простоты этот контейнер управления зависимостями -именно то, что нужно.
02.11.16
Посмотреть всех экспертов из раздела Технологии > .Net/C#
Пользуйтесь нашим приложением Доступно на Google Play Загрузите в App Store