Sorry in advance for the long question, it's long because I've been digging at this all day.
I have an ASP.Net MVC2 application with the following projects: MyApp.Web, MyApp.Services, MyApp.Data.
We code to interfaces and utilize Ninject 2 for DI/IoC.
However, I'm getting awfully tired of typing (and forgetting to type):
Bind<ISomeService>.To<SomeService>;
So, knowing about Ninject.Extensions.Convensions, I have attempted to use it to automatically scan and register modules and simple dependencies of the type IXxxx => Xxxx.
I can use the following code to setup Ninject, and everything seems to get wired up as expected.
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;
}
However ... I'd like to take this a bit further in a way I think is supported, but I cannot seem to get it working.
Since our MyApp.Web project uses nothing at all (directly) from MyApp.Data, I am trying to avoid a reference to MyApp.Data. With the above code, I must reference MyApp.Data from MyApp.Web because of the compile time reference to SomeDataClass.
I would prefer to specify the name of an assembly for Ninject to scan and register. It seems the Conventions extension supports this through the From overloads that take a string (or enumerable of strings).
So, I've tried several variations on the From overloads:
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;
}
But I receive FileNotFoundExceptions with a message like:
Could not load file or assembly 'file:///C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\MyApp.Data' or one of its dependencies. The system cannot find the file specified.":"file:///C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\
I've checked out the source for Ninject.Extensions.Conventions, and I'll admit I get totally lost as to how this is supposed to work, but I can see what it is doing.
The assembly scanner builds up a list of assemblies to scan as we call various FromXXX methods.
When I call the From("assemblyName") method, it first checks if the list already contains any assemblies where the assembly.AssemblyName.Name equals the name I passed in (and AssemblyName.Name is the simple name, i.e. MyApp.Data, according to MSDN).
Flow passes through a couple unimportant methods, landing in the FindAssemblies method. This method takes the name I passed in (which we already saw is supposed to be a simple assembly name). It then creates a new AssemblyName, with our passed in name used as the AssemblyName.CodeBase.
Then, it attempts to Load the assembly into a temporary AppDomain. This is the step that fails with the above exception.
Obviously, the path it's searching is wrong, but I cannot supply a path through the From() method. That doesn't work either.
I've tried some of the other FromXXX methods, but I've gotten nowhere and spent too much time on this already. The FromAssembliesInPath and FromAssembliesMatching also do not work because, again, it is searching in the completely wrong directory.
Can anyone explain how to get Ninject Conventions to load assemblies by name, without creating a reference to the assembly and loading it by specifying a contained type? Please.
I've already searched through pages and pages of the Ninject google group, and I've read it's only (so it seems) relevant documentation and have not been able to solve it .. yet.
This question was answerd on the mailing list. http://groups.google.com/group/ninject/browse_thread/thread/a7f2163e060a6d64
In Short:
I'm not sure if this is a typo in your example, but I did notice that you've written
kernel.Scan(a => {
a.From("MyApp.Data");
// etc.
}
But shouldn't that be
kernel.Scan(a => {
a.From("MyApp.Data.dll")
// etc.
});
Because if I include the .dll part in my example project it works, but if I leave it out I receive a FileNotFoundException.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With