Извините за длинный вопрос, это долго, потому что я копаю в этом весь день.
Общая проблема:
У меня есть приложение 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 с таким сообщением, как:
Не удалось загрузить файл или сборку
'file: /// 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 - simple name, т.е. MyApp.Data, согласно MSDN).
Поток проходит через пару неважных методов, приземляясь в методе FindAssemblies. Этот метод принимает имя, которое я передал (которое мы уже видели, должно быть простым именем сборки). Затем он создает новое AssemblyName, с нашим переданным именем, используемым как AssemblyName.CodeBase.
Затем он пытается загрузить сборку во временный домен приложений. Это шаг, который завершается неудачей с вышеуказанным исключением.
Очевидно, что путь, который он ищет, неверен, но я не могу указать путь через метод From (). Это тоже не работает.
Я пробовал некоторые другие методы FromXXX, но я ни к чему не привел и уже потратил слишком много времени на это. Сопоставление FromAssembliesInPath и FromAssemblies также не работает, поскольку, опять же, он выполняет поиск в совершенно неправильном каталоге.
Э-э ... что за вопрос был снова:
Может кто-нибудь объяснить, как заставить Ninject Conventions загружать сборки по имени, не создавая ссылку на сборку и загружая ее, указав содержащийся тип? Пожалуйста.
Я уже просмотрел страницы и страницы группы Ninject google и прочитал только (как мне кажется) соответствующую документацию и не смог решить это .. пока.