Assembly Identity

There are two types of assembly identity that the loader deals with: bind-time and after bind-time. The identity is used to determine whether we will consider a certain assembly to be the same thing as an assembly reference or another assembly.

Assembly Binding
At assembly-bind time, the components of the assembly display name determine identity. This will be used to match an assembly reference (the assembly that the user wants to load) to a manifest file.

Not all of the components matter in all cases. If the assembly is not strongly-named, then the version is ignored for binding. But, if it is strongly-named, the entire version in the assembly reference needs to match the found assembly.

There are other details about what is and isn’t necessary to specify for binding, but please always give the entire display name EVERY time, anyway. Otherwise, you are asking for trouble!!

Comparing Already-Loaded Assemblies
Unless this comparison is for binding, the path to the manifest file of this assembly is used for determining whether this is the same assembly as another one.

For example, path matters when determining whether a type is castable to another type. Even if the assemblies containing the types are identical, if they’re loaded from different paths, they’re considered different assemblies and therefore their types are different. This is one reason why using contexts other than the Load context is risky. You can get into situations where the same assembly is loaded multiple times in the same appdomain (once in the Load context, once in the LoadFrom context, and even several times in neither context), and their corresponding types won’t be castable.

Some assemblies don’t have paths associated with them, such as those loaded by Load(byte[]) or created by Reflection Emit. Those are always just considered different assemblies, even if all of their bytes are identical.

Comments (16)

  1. Yiru Tang says:

    If I load one assembly through
    And load another assembly in a different appDomain also use LoadFrom(path) (through CreateInstanceFrom actually, but the assembly is from same path).
    Should the two assembly be considered the same? Seems they are not considered same now.
    However if I use Load Context in different appdomains, the loaded assembly are considered the same.

  2. Suzanne says:

    For identity purposes, identical assemblies in different appdomains are by definition not "the same" as each other. They are not directly comparable to each other. When we do compare them, the comparison happens in only one appdomain, and the assembly that’s not already there will be reloaded into it. At that point, their paths would be compared.

    It sounds like when you count them as being "the same," you really mean that it’s being loaded as domain neutral. The behavior you described is expected – assemblies loaded in the LoadFrom context are not loaded as domain neutral.

  3. Richard says:

    I am having trouble loading an assembly from an appdomain when the exe is unmanaged and call’s my dll through com.


    My dll is found and loaded:


    But my dll references another dll:


    Fusion says that it is looking for the both dll’s in c:app, but mydll.dll is found and the thirdParty.dll throws a fileNotFound Exception. Both have strong names and reside in the GAC.

    First, how is my dll still loaded and more importantly, why is the third party dll not. This only occurs when installed on a client machine? Any ideas. Should I use Assembly.Load and manually load? Thanks.

  4. Suzanne says:

    It sounds like, in the failure case, the Fusion log says that it is probing the application base for the third party dll. That means that it was not found in the GAC. Call "gacutil /l thirdParty" from the failing environment and make sure that the assembly with the exact same, post-policy display name as listed in the Fusion log is in the GAC.

  5. Richard says:

    Your correct. I used installshield to ngen the assembly and it did show up in the assembly folder in windows, but using gacutil /l shows that it is ngen’d in the cahce but not in the GAC. I assumed that the two where the same, but apparently they aren’t.

    To solve the problem I’ll attempt to get installshield to put it in the GAC and see if that resolves the problem.


  6. Dave Friedel says:

    Thank you sooo much.  

    I seriously feel that if the 2 identical assemblies with strong-names (only located in different directories) should be allowed to load without causing a type-mismatch of objects created and exhanged between – since they are strong-named to say they are the same.  

    But as it goes, it caused me to pull un-necessary hair out when moving to strong-name – when I felt the files were (and are) identical.  I would very much like them to add a property to allow this to happen (when the files are identical with strong names – since it functions without strong names)



    p.s. thank you again.

  7. Thanks to Suzanne Cook for this one. "First, obviously, find the two types for which the cast failed,

  8. First, obviously, find the two types for which the cast failed and verify that they are the same type

  9. Be careful – these aren’t the same thing. LoadFrom() goes through Fusion and can be redirected to another

  10. Stephen Gyves says:

    I am trying to create an assembly comparer. I already have created objects to hold information about assemblies, types, enums…etc. So once I ahve collected information about the assembly, I don;t need it anymore to perform the comparison. Trouble is this, I have to find a way to compare assemblies even if the SAY they are the same version. How can I safely retrieve infromation from both assemblies?

  11. El Guapo says:

    Stephen, check out an assembly comparison tool called BitDiffer. It can compare assemblies with identical identities…