Извините заранее за длинный вопрос, это долго, потому что я все время копаю весь этот день.
Общая проблема:
У меня есть приложение 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, и я прочитал его только (так кажется) соответствующей документации и еще не удалось ее решить..