2

UPDATE: I failed to mention, I am using Castle version 2.5.1.0 (there are a number of dependencies that mean we haven't gone to something newer)

I have been using a number of frameworks which leverage Castle Windsor and have had pretty good luck with it. On a few occasions, I have hit cases where I get an exception when trying to install from AppConfig because of some missing reference. From what I can tell, when I do something like container.Install(Configuration.FromAppConfig()); Castle will load all of the components registered in the config file. From each assembly containing components which are registered, I believe Castle will then examine that assembly's manifest and then load those assemblies, and continue in that manner until all required assemblies are loaded.

That leads to the problem I am having. I wrote some code using unit tests. The code loads several components using the Configuration.FromAppConfig() method. It then resolves the components by name, when needed. The unit tests work fine. When I call this code in my MVC controller, I start getting errors in the call to Configuration.FromAppConfig(). Here is some sample code:

This is a simplified version, but illustrates the problem:

public interface IAuthorizer2
{
    string Url { get; set; }
}

public class Foo : IAuthorizer2
{
    public string Url { get; set; }
}

This is the component in web.config:

  <component id="MessageManagerAdmins" service="MsmqManager.Areas.MessageManager.Controllers.IAuthorizer2"
type="MsmqManager.Areas.MessageManager.Controllers.Foo"/>

In my controller action I call:

var container = new WindsorContainer();
container.Install(Configuration.FromAppConfig());

I get the following exception: (I'm including the whole thing for completeness)

    Could not load file or assembly 'Spatial4n.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f9456e1ca16d45e' or one of its dependencies. The system cannot find the file specified.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.IO.FileNotFoundException: Could not load file or assembly 'Spatial4n.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f9456e1ca16d45e' or one of its dependencies. The system cannot find the file specified.

Source Error: 


Line 100:        {
Line 101:            var container = new WindsorContainer();
Line 102:            container.Install(Configuration.FromAppConfig());

Source File: c:\Prj\AA\Source\Development\Web\MessageManager\Source\MessageManager\Areas\MessageManager\Controllers\MessageController.cs    Line: 102 

Assembly Load Trace: The following information can be helpful to determine why the assembly 'Spatial4n.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f9456e1ca16d45e' could not be loaded.


=== Pre-bind state information ===
LOG: User = ARCHSTONE\tstappaa
LOG: DisplayName = Spatial4n.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f9456e1ca16d45e
 (Fully-specified)
LOG: Appbase = file:///C:/Prj/AA/Source/Development/Web/AssociatePortal/Source/AssociatePortal/
LOG: Initial PrivatePath = C:\Prj\AA\Source\Development\Web\AssociatePortal\Source\AssociatePortal\bin
Calling assembly : Lucene.Net.Contrib.Spatial, Version=2.9.1.2, Culture=neutral, PublicKeyToken=85089178b9ac3181.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Prj\AA\Source\Development\Web\AssociatePortal\Source\AssociatePortal\web.config
LOG: Using host configuration file: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Spatial4n.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f9456e1ca16d45e
LOG: The same bind was seen before, and was failed with hr = 0x80070002.

It is looking for the Spatial4n.Core assembly. I have never heard of this assembly before now. I traced it down to: the site uses RavenDB Raven.Database assembly references Spatial4n.Core.

I can understand why Castle would attempt to resolve all of the assemblies that may be called as a result of Resolving a component. However, if you look at the definition of the interface/class I am working with, there aren't any dependencies here. I know that I can go download a copy of the Spatial4n.Core assembly, and all of the rest of the assemblies that would be required, but I want to understand how to properly configure the container to avoid this issue.

My questions:

  • Is there a better way to populate the container/register components so that I can resolve them by type and name(i.e. container.Resolve("componentName"))
  • Is there a way to tell Castle to not resolve every possible assembly reference?
  • I did a lot of searching on the Castle Project site and elsewhere. I haven't found anything informative about how Castle resolves these assembly references. It mostly is about the more basic functions of configuring a container. Can you recommend deeper documentation where I can learn more about this?

Thanks.

4

1 に答える 1

1

That's not exactly Windsor's behavior, but System.Reflection. When an assembly is loaded, the dependencies are not loaded, but since you're using 'AllTypes' that means every single type - including private will be loaded (through reflection) and that prompts the loader to resolve the dependencies.

The way to avoid that is to use explicit registration Component.For<> etc...

WRT resolving by name, by default the full type name is used as the key (namespace + type name)

Documentation is weak, but source code is not too complex. There are also plenty of blog posts.

HTH

于 2012-10-31T05:05:03.753 に答える