Я только начал работать с внедрением зависимостей в первый раз, и я использую Ninject 2.0 в качестве контейнера IoC на веб-сайте ASP.NET MVC 2, и у меня возникает ошибка активации, на которую я не знаю, как реагировать. Я уверен, что это просто, поэтому надеюсь, что кто-то сможет указать мне правильное направление без особых размышлений.

У меня есть свойство в моем классе BaseController, которое принимает IWebsiteSettings и помечено атрибутом [Inject]. В моем StandardKernel я загружаю модуль со следующим кодом:

public class WebModule : Module
{
    public override void Load()
    {

        Bind<IWebsiteSettings>()
            .ToProvider(new WebsiteSettingsProvider(WebConfigurationManager.AppSettings))
            .InSingletonScope();

    }
}

public class WebsiteSettingsProvider : Provider<WebsiteSettings>
{
    private const string WebsiteNameKey = "Website.Name";
    private const string ContactFormEmailSubjectKey = "ContactForm.EmailSubject";
    private const string ProductImageDirectoryKey = "Products.ImageDirectory";
    private const string UploadTempDirectoryKey = "Uploads.TempDirectory";

    protected NameValueCollection Settings { get; set; }

    public WebsiteSettingsProvider(NameValueCollection settings)
    {
        Settings = settings;
    }

    protected override WebsiteSettings CreateInstance(IContext context)
    {
        return new WebsiteSettings
                   {
                       WebsiteName = Settings[WebsiteNameKey] ?? string.Empty,
                       ContactFormEmailSubject = Settings[ContactFormEmailSubjectKey] ?? string.Empty,
                       ProductImageDirectory = Settings[ProductImageDirectoryKey] ?? string.Empty,
                       UploadsTemporaryDirectory = Settings[UploadTempDirectoryKey] ?? string.Empty
                   };
    }
}

Это довольно просто - я пытаюсь загрузить некоторые данные из файла web.config и сохранить их в одноэлементном объекте для использования на моих контроллерах. Вызов Bind, похоже, работает именно так, как должен, и свойство Settings в моем провайдере правильно инициализировано с помощью коллекции AppSettings в файле конфигурации. Тем не менее, когда приложение загружается в первый раз:

Server Error in '/' Application.
Error activating SByte* using implicit self-binding of SByte*
No constructor was available to create an instance of the implementation type.

Activation path:
 4) Injection of dependency SByte* into parameter value of constructor of type string
 3) Injection of dependency string into property WebsiteName of type WebsiteSettings
 2) Injection of dependency IWebsiteSettings into property WebsiteSettings of type HomeController
 1) Request for HomeController

Suggestions:
 1) Ensure that the implementation type has a public constructor.
 2) If you have implemented the Singleton pattern, use a binding with InSingletonScope() instead.

Интересно, что если я обновляю страницу, я не получаю исключения, а вызов Kernel.Get () возвращает правильный объект.

Любой совет?

2
Nathan Taylor 27 Авг 2009 в 00:32

2 ответа

Лучший ответ

(Мы говорили об этом в IRC, но я помещаю это здесь на случай, если кто-то еще столкнется с этой проблемой.)

WebsiteSettings имеет атрибуты [Inject] в своих свойствах, поэтому Ninject пытается разрешить привязку из System.String, чтобы ввести значение в свойства. Поскольку вы используете настраиваемый поставщик для активации экземпляров WebsiteSettings, вам не нужны атрибуты [Inject] в его свойствах.

2
Nate Kohari 27 Авг 2009 в 02:05

На самом деле код нарушения был в классе WebsiteSettings, где я делал это:

public class WebsiteSettings : IWebsiteSettings
{
    [Ninject.Inject]
    public string WebsiteName
    {
        get; set;
    }

    [Ninject.Inject]
    public string UploadsTemporaryDirectory
    {
        get; set;
    }

    [Ninject.Inject]
    public string ContactFormEmailSubject
    {
        get; set;
    }

    [Ninject.Inject]
    public string ProductImageDirectory
    {
        get; set;
    }
}

Помещая атрибут Inject в свои свойства, я заставлял Ninject пытаться присвоить значения, которые я никогда не связывал. Поскольку я использую Provider для загрузки своего типа, мне не нужно включать атрибут Inject.

0
Nathan Taylor 27 Авг 2009 в 02:06