Веб-формы Ninject + ASP.NET не работают - PullRequest
2 голосов
/ 19 сентября 2011

Я успешно реализовал Ninject в приложении MVC3, но у меня возникли некоторые проблемы, связанные с веб-формами ASP.NET. Я получаю нулевые ссылки каждый раз, когда пытаюсь получить доступ к внедренному свойству на бизнес-уровне. После установки точек останова в методе CreateKernel, а также в нескольких местах в классе ServiceLocator создается впечатление, что ни одно из них никогда не получает удар, поэтому он даже не загружается.

Я уверен, что я просто подхожу к этому неправильно, но там очень мало документации или информации для подключения Ninject в приложении Web Forms.

В основном вот что у меня есть:

код позади

public class ReviewManager
    {
        [Inject] private IReviewRepository _reviewRepository { get; set; }

        public ReviewManager() { }

        public ReviewManager(IReviewRepository reviewRepository)
        {
            _reviewRepository = reviewRepository;
        }

        public Review GetById(int id)
        {
            if (id <= 0) throw new ArgumentException("ID must be greater than zero");

            **I get a null reference exception on the next line. _reviewRepository is null**
            return _reviewRepository.GetById(id);
        }
}

Global.asax.cs

public class Global : NinjectHttpApplication
{
    protected override IKernel CreateKernel()
    {
        return ServiceLocator.Kernel;
    }

    // deleted for brevity
}

ServiceLocator.cs (отредактировано для краткости, соответствующие части здесь)

public static class ServiceLocator
    {
        public static IKernel Kernel { get; set; }

        public static ILogger Logger { get; set; }

        static ServiceLocator()
        {
            Kernel = new StandardKernel(new INinjectModule[] {
                new LoggerBindings(),
                new DataBindings()
            });

            if (Logger == null)
                Logger = Kernel.Get<ILogger>();
        }
}
public class LoggerBindings : NinjectModule
    {
        public override void Load()
        {
            Bind<ILogger>().To<NLogLogger>();
        }
    }

    public class DataBindings : NinjectModule
    {
        public override void Load()
        {
            Bind<IReviewRepository>().To<ReviewRepository>();
        } 
    }

Ответы [ 4 ]

2 голосов
/ 20 сентября 2011

Крутая вещь в MVC состоит в том, что он может работать на стороне страниц ASP.NET WebForm в одном приложении.На мой взгляд, лучший способ расширения веб-сайтов ASP.NET WebForms - это создание новых страниц с использованием MVC3 и рефакторинг каждой страницы, которая требует серьезных изменений в MVC3.

Если это не вариант, перейдите и используйте Ninject.Web.расширение.Он содержит IHttpModule, свойство которого внедряет все веб-страницы и элементы управления после их инициализации.Таким образом, вы можете добавлять свойства в сервисы, если они созданы Ninject.

2 голосов
/ 19 сентября 2011

ASP.Net через WebForms не позволяет вам управлять жизненным циклом всех экземпляров объектов (как это делает MVC).Например, каркас создает экземпляры объектов страницы.Это означает, что вы, вероятно, не сможете реализовать DI так же, как в MVC / WPF / Silverlight (такая же проблема присутствует в WinForms IIRC).Скорее всего, вам придется инициировать граф зависимостей непосредственно в каждом из ваших кодов.

Перевод: вам нужно будет вызвать ServiceLocator.Kernel.Get<IReviewRepository>, когда ваша страница загружается (или как lazy-init для свойства).

0 голосов
/ 24 мая 2012

Я использую инъекцию свойств для страниц, мастер-страниц и пользовательских контролей.Например, все мои страницы наследуются от базового класса, который переопределяет метод RequestActivation со следующим кодом:

    ''' <summary>
    ''' Asks the kernel to inject this instance.
    ''' </summary>
    Protected Overridable Sub RequestActivation()
        ServiceLocator.Kernel.Inject(Me)
    End Sub

И на каждой странице я объявляю свойства для инъекций:

    <Inject()>
    Property repo As IMyRepository
0 голосов
/ 20 сентября 2011

Возможный обходной путь, изменив класс DataBindings следующим образом:

 public class DataBindings : NinjectModule 
    { 
        public override void Load() 
        { 
            Bind<IReviewRepository>().To<ReviewRepository>(); 
            Bind<ReviewManager>().ToSelf();
        }  
    } 

И внутри вашего абонента вместо

var rm = new ReviewManager();

Попробуйте использовать

var rm = ServiceLocator.Kernel.Get<ReviewManager>();

Я не проверял этот код, но я думаю, что он решит вашу проблему с нулевой ссылкой.

...