Подтвердить что ты не робот

Как использовать расширение Ninject Conventions без ссылки на сборку (или типы внутри нее)

Извините заранее за длинный вопрос, это долго, потому что я все время копаю весь этот день.

Общая проблема:

У меня есть приложение ASP.Net MVC2 со следующими проектами: MyApp.Web, MyApp.Services, MyApp.Data.

Мы кодируем интерфейсы и используем Ninject 2 для DI/IoC.

Однако мне становится ужасно устало печатать (и забывать вводить):

Bind<ISomeService>.To<SomeService>;

Итак, зная о Ninject.Extensions.Convensions, я попытался использовать его для автоматического сканирования и регистрации модулей и простых зависимостей типа IXxxx = > Xxxx.

То, что я пробовал, работает (но этого недостаточно):

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

    public static IKernel Initialize()
    {
        var kernel = new StandardKernel();

        kernel.Scan(a => {
                        a.FromAssemblyContaining<MyApp.Data.SomeDataClass>();
                        a.FromAssemblyContaining<MyApp.Services.SomeServiceClass>();
                        a.AutoLoadModules();
                        a.BindWithDefaultConventions();
                        a.InTransientScope();
                    });

        return kernel;
    }

Что я хочу сделать вместо этого:

Однако... Я бы хотел сделать это немного дальше, как мне кажется, поддерживается, но я не могу заставить его работать.

Так как наш проект MyApp.Web ничего не использует (напрямую) из MyApp.Data, я пытаюсь избежать ссылки на MyApp.Data. С приведенным выше кодом я должен ссылаться на MyApp.Data из MyApp.Web из-за ссылки времени компиляции на SomeDataClass.

Я бы предпочел указать имя сборки для Ninject для сканирования и регистрации. Кажется, что расширение Conventions поддерживает это через перегрузки From, которые берут строку (или перечисляют строки).

Что я пытался и как он ломался:

Итак, я пробовал несколько вариантов перегрузки From:

    public static IKernel Initialize()
    {
        var kernel = new StandardKernel();

        kernel.Scan(a => {
                        a.From("MyApp.Data");
                        a.From("MyApp.Services.dll");
                        a.From("AnotherDependency, Version=1.0.0.0, PublicKeyToken=null"); //etc., etc. with the From(...)'s
                        a.AutoLoadModules();
                        a.BindWithDefaultConventions();
                        a.InTransientScope();
                    });

        return kernel;
    }

Но я получаю FileNotFoundExceptions с сообщением вроде:

Не удалось загрузить файл или сборку 'файл:///C:\Program Files (x86)\Общие файлы \Microsoft Общий\DevServer\10.0\MyApp.Data "или одной из его зависимостей. Система не удается найти файл указанный.":" файл:///C:\Program Files (x86)\Общие файлы \Microsoft Общий\DevServer\10,0\

То, что я нашел, пытается решить это сам:

Я проверил источник для Ninject.Extensions.Conventions, и я признаю, что полностью потерял, как это должно работать, но я вижу, что он делает.

Сборочный сканер создает список сборок для сканирования, поскольку мы вызываем различные методы FromXXX.

Когда я вызываю метод From ( "assemblyName" ), он сначала проверяет, содержит ли список уже какие-либо сборки, где assembly.AssemblyName.Name равно имени, которое я передал (и AssemblyName.Name - это простое имя, то есть MyApp.Дата, согласно MSDN).

Поток проходит через пару неважных методов, посадку в методе FindAssemblies. Этот метод принимает имя, которое я передал (мы уже видели, это должно быть простое имя сборки). Затем он создает новое AssemblyName, с нашим переданным именем, используемым как AssemblyName.CodeBase.

Затем он пытается загрузить сборку во временный AppDomain. Это шаг, который не соответствует указанному выше исключению.

Очевидно, что путь, который он ищет, неверен, но я не могу предоставить путь через метод From(). Это тоже не работает.

Я пробовал некоторые другие методы FromXXX, но я нигде не стал и потратил слишком много времени на это уже. FromAssembliesInPath и FromAssembliesMatching также не работают, потому что, опять же, он ищет в совершенно неправильной директории.

Э-э... в чем вопрос снова:

Может ли кто-нибудь объяснить, как заставить Ninject Conventions загружать сборки по имени, не создавая ссылку на сборку и не загружая ее, указав содержащийся тип? Пожалуйста.

Я уже просматривал страницы и страницы Ninject google group, и я прочитал его только (так кажется) соответствующей документации и еще не удалось ее решить..

4b9b3361

Ответ 1

Этот вопрос был answerd в списке рассылки. http://groups.google.com/group/ninject/browse_thread/thread/a7f2163e060a6d64

Вкратце:

  • Форма (путь) принимает путь либо относительный от рабочего каталога, либо абсолютный
  • Сборка должна находиться в пути исследования, поскольку она загружается в контекст нагрузки, чтобы избежать других проблем с переключением контекста загрузки.
  • Сервер разработки делает все сложнее, поскольку он копирует все сборки в свой собственный каталог, что делает невозможным использование вызывающей сборки для создания пути. Это означает единственный способ использования веб-приложений на сервере разработки.
  • Мы добавим поддержку для полнофункциональных имен сборок в будущей версии, чтобы сделать это проще.

Ответ 2

Я не уверен, что это опечатка в вашем примере, но я заметил, что вы написали

kernel.Scan(a => {
    a.From("MyApp.Data");
    // etc.
}

Но не должно быть

kernel.Scan(a => {
    a.From("MyApp.Data.dll")
    // etc.
});

Потому что, если я включаю часть .dll в мой примерный проект, он работает, но если я его оставлю, я получаю исключение FileNotFoundException.