views:

72

answers:

4

I have the following class located in Assembly A. The assembly has a reference to StructureMap 2.6.1.

public static class Bootstrapper
{
    public static void Bootstrap(string databaseName)
    {
        StructureMapBootstrapper.Bootstrap(databaseName);
    }
}

I'm referencing Assembly A in a completely different Assembly (B) and I"m getting the following runtime error when this line is called:

Bootstrapper.Bootstrap(db);

The runtime error is:

FileNotFoundException: Could not load file or assembly 'StructureMap, Version=2.6.1.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223' or one of its dependencies. The system cannot find the file specified.

I'm constantly having to copy StructureMap.dll to the bin directory of Assembly B. This is incredibly annoying. Any suggestions on how to resolve this? Does anybody know the general rules regarding when assemblies referenced by AssemblyA will be needed by AssemblyB?

Thanks!

+1  A: 

To avoid copying the DLL, you could add the StructureMap.dll to your project and have VS automatically copy it to the output upon building AssemblyA.

Or, you could use ILMerge to merge StructureMap.dll into Assembly B, and not worry about copying it, as Assembly B will contain all the IL needed.

Or, you can add StructureMap.dll to the Global Assembly Cache, which should allow .NET to find it without having to copy it. However, IIRC, all GAC assemblies need strong names.

Alan
A: 

As an aside, since the assembly has a strong name (you can see this by the fact that it has a value for PublicKeyToken), you could install the StructureMap assembly into the GAC, which would make it available to any .NET application running on the system. This will likely solve your problem.

As for deploying with the assembly in the GAC, it depends on how you plan to deploy. I'm assuming that this is a Winforms application, so I'm also assuming that you'll be deploying through a setup project. If that's the case, then it's easy to include the assembly that's supposed to go in the GAC in the project, and it will install it there if it isn't present.

To answer your question, though, assembly binding and loading are somewhat nuanced, but the general rule is that an assembly is loaded the first time a type that is contains is loaded. A type is loaded as soon as a block of code that references is on the active stack frame.

The last sentence essentially boils down to this: a type is loaded when either of the following happens:

  • Another type is loaded that uses the type in question as an instance or static variable

For example, say I have types A, B, and C.

public class A
{

}

public class C
{

}

public class B
{
    private A myA;
    private static C myC;
}

When type B is loaded, it will also load A because it's used as an instance variable, and C will get loaded because it is used as a static variable.

  • A function that uses the type in question as a local variable, parameter, or calls another function that uses it as a parameter.
Adam Robinson
A: 

Thanks for the quick replies! I thought about simply adding StructureMap as a reference. However, the angle I was going for in my design was to abstract underlying implementations away from the consumer. In other words, Assembly B would be ignorant to the fact that StructureMap was ultimately being used. Also, if I GAC StructureMap, then I would run into deployment issues right? If I deploy a site to a host machine which doesn't have StructureMap in its Global Cache, then I'm back to square one. I'm curious how true abstraction could be realized given this assembly referencing issue.

ActionJackson
Please don't post follow-ups to your questions as answers. You can edit your original question by clicking "edit" near the bottom. Thanks! Once you do that, please delete this answer.
Adam Robinson
+1  A: 

There is an excellent tool called Refix that you could use to inspect and fix your dependencies. Refix

Daniel Dyson