which assembly will be called?

Hi,

I am studying .net and run it this question:

Assembly A calls a private assembly B to do some function. B is located in the bin directory of A. Later you You assign B a strong name, set its version to 1.0.0.0, and install it in the global assembly cache.

In this case, which B the assembly A will call is it still the B in bin or it is from global assembly cache

Many Thanks

Jerry



Answer this question

which assembly will be called?

  • dez66


    First bin then GAC.
    Once you have a dll in bin and GAC you application will always seek first bin then GAC in order to force application to go to GAC delete dll from bin.

  • mathieu.szablowski

    If you've not recompiled Assembly A, then its reference to B will not include the strong name. So the CLR will not look in the GAC.

    The GAC is only used when attempting to resolve a strongly-named assembly. (You cannot put an assembly in the GAC unless it is strongly named.)

    Assembly resolution will only resolve to a strongly-named assembly if you are attempting to locate a strongly-named assembly. The reasoning here is that if you were trying to load a strongly-named assembly you would have specified the strong name. Since you only provided a weak name, it would be an error to give you the strongly-named assembly because if you wanted the strongly named one you would have asked for it.

    It all changes if you recompiled A against the newly strongly-named assembly though. If you recompile A against the new B, A's reference to B will now contain the strong name. So in this case, it will get the one from the GAC.

    I'm afraid Mubshir Raza Ali is completely wrong here, so please ignore what he says. There is no situation in which the CLR will try bin first and then the GAC. The two options are:

    1. GAC first, then local
    2. Local only

    If your assembly reference specifies a strong name it will always use option 1. If not it will always use option 2.

    You can use ILDASM to see whether you've got a strong reference. Open up the "M A N I F E S T" section. Strong name references incorporate a .publickeytoken, like this:

    .assembly extern mscorlib

    {

      .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )

      .ver 2:0:0:0

    }

    But a weakly named reference will not contain that .publickeytoken part. This is what determines how assembly resolution will proceed. It will only look in the GAC if Assembly A's reference to Assembly B contains that .publickeytoken part.

    Note, if you've not rebuilt Assembly A, but you've changed Assembly B to have a strong name, and you've overwritten the old local weakly-named copy in your bin dir with this new strongly-named copy, assembly resolution will fail. You'll see something like this:

    Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'AssemblyB, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

    This is because if you attempt to load a weakly-named assembly, but assembly resolution ends up finding a strongly-named assembly, this is deemed to be a failure. (Again, because if you wanted a strongly-named assembly, you'd have asked for one.)

    So regardless of whether you use the GAC or not, you're going to have to rebuild Assembly A if you've changed B from weakly to strongly named.

    Unless that is you leave a copy of the original Assembly B in the bin directory. In that case, if you have a strongly-named assembly B in the GAC, and the original weakly-named Assembly B in the local dir, and Assembly A has a reference to the weakly-named B, it won't bother to look in the GAC (because you've not used a strong name reference), and will continue to pick up the local version.

    Basically, a strongly-named Assembly B is considered to be completely unrelated to a weakly named Assembly B - the two effectively have different names. Adding a strongly-named assembly to the GAC with a local name that happens to match the local name of a weakly-named assembly does not replace that weakly-named assembly.

    For example, if you add a weakly-named assembly called System.Xml, this will be considered to be a completely different assembly from the strongly-named System.Xml that ships with the .NET Framework. So if you try to load your weakly named System.Xml, you'll get your local weakly named one.


  • sydes141

    Hi Suresh,

    The assembly in bin is not recompiled, so still the private assembly. Only the one in GAC is recompiled.

    So it should be bin first, isn't it

    Thanks


  • Tibor Biro

    Hi IanG,

    Thanks for your post and it reads technically sound. I just post the question I am trying to answer:

    You have an ASP.NET application named WebApp. This application uses a private assembly named Employee to store and retrieve employee data. Employee is located in the bin directory of WebApp.

    You develop a new ASP.NET application named WebApp2 that also needs to use Employee. You assign Employee a strong name, set its version to 1.0.0.0, and install it in the global assembly cache. You then create a publisher policy assembly for version 1.0.0.0 and install it in the global assembly cache.

    You compile WebApp2 against version 1.0.0.0. You do not recompile WebApp. You then run WebApp.

    What is the most likely result

    A. A VersionNotFoundException is thrown.
    B. Employee is loaded from the bin directory.
    C. Version 1.0.0.0 of Employee is loaded from the global assembly cache.
    D. Version 1.0.0.0 of Employee is loaded by the publisher policy assembly.

    As you said, as WebApp was not recompiled, it just goes to the class in BIN. However, if it is recompiled, it will load the employee class by publisher policy assembly.

    Is my understanding right

    Many Thanks

    Jerry


  • p4Pratik

    Assuming that you use VS .NET, if you added Assembly B as reference to Assembly A,Assembly A will use the GAC version if it (Assembly A) is recompiled.Otherwise it will use Bin version.

    Thanks,

    Suresh.


  • Vaylor Trucks

    Your understanding looks correct to me.

    The one thing I'm not sure about is why the question mentions publisher policy. Publisher policy is something you can set up to say "Any application that asks for version X should use version Y instead by default." So it's something that only makes sense once you've moved onto the second version. Since this is version 1.0.0.0, you wouldn't expect to see a publisher policy. Publisher policy is something that might come into the picture if you had a bug-fix release. (E.g. 1.0.1.0...)

    I suppose that aspect of the question is just trying to mislead you into thinking that maybe WebApp will use the GAC version because of the publisher policy. But it won't. The publisher policy won't make any difference to anything at this stage - publisher policy is only used for strongly-named assemblies.

    So it looks to me like your understanding is correct.

    Even so, I would strongly recommend building an example to test it. If you actually go ahead and construct two web applications in exactly the same way as described here, you'll have a definitive answer! (Back when I started learning .NET, way back in 2000 when the documentation was rather sparse, I did most of my learning by building experimental applications in order to discover the answers to questions like these.) It's a great way to learn, I find. And is a far more reliable way of getting correct answers to questions than relying on people posting to a forum. ;-)


  • albTotxo

    Hi,

    I guess it depends on how and when you compile Assembly A.If the referenced assembly is having a public key the CLR will look for the assembly in GAC first,however if you dont recompile Assembly A it will still refer to bin.

    Thanks,

    Suresh.


  • which assembly will be called?