Assembly.LoadFrom/LoadFile/Load(byte[]) prefers GAC
Starting in Whidbey beta2, for Assembly.LoadFrom/LoadFile/Load(byte[]) , if there is an assembly in GAC with exactly the same assembly identity, we will return the one in GAC.
ReflectionOnlyLoad and ReflectionOnlyLoadFrom APIs are not affected.
C:\>more f:\tools\fullname.cs
using System;
using System.IO;
using System.Reflection;
class MyApp
{
public static void Main(String[] argv)
{
if (argv.Length < 1)
{
Console.WriteLine("Usage: FullName assembly");
return;
}
String path = Path.GetFullPath(argv[0]);
try
{
Console.WriteLine("Using Assembly.LoadFrom:");
Assembly a = Assembly.LoadFrom(path);
AssemblyName an = a.GetName();
Console.WriteLine("FullName: " + an.FullName);
Console.WriteLine("Location: " + a.Location);
Console.WriteLine("Codebase: " + a.CodeBase);
Console.WriteLine();
Console.WriteLine("Using Assembly.LoadFile:");
a = Assembly.LoadFile(path);
an = a.GetName();
Console.WriteLine("FullName: " + an.FullName);
Console.WriteLine("Location: " + a.Location);
Console.WriteLine("Codebase: " + a.CodeBase);
Console.WriteLine();
Console.WriteLine("Using Assembly.Load(byte[]):");
byte[] bytes = File.ReadAllBytes(path);
a = Assembly.Load(bytes);
an = a.GetName();
Console.WriteLine("FullName: " + an.FullName);
Console.WriteLine("Location: " + a.Location);
Console.WriteLine("Codebase: " + a.CodeBase);
Console.WriteLine();
Console.WriteLine("Using Assembly.ReflectionOnlyLoadFrom:");
a = Assembly.ReflectionOnlyLoadFrom(path);
an = a.GetName();
Console.WriteLine("FullName: " + an.FullName);
Console.WriteLine("Location: " + a.Location);
Console.WriteLine("Codebase: " + a.CodeBase);
}
catch( Exception e)
{
Console.WriteLine("Exception: {0}", e.Message);
}
}
}
C:\WINDOWS\Microsoft.NET\Framework\v2.0.41101>f:\tools\fullname system.dll
Using Assembly.LoadFrom:
FullName: System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Location: C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll
Codebase:
Using Assembly.LoadFile:
FullName: System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Location: C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll
Codebase:
Using Assembly.Load(byte[]):
FullName: System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Location: C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll
Codebase:
Using Assembly.ReflectionOnlyLoadFrom:
FullName: System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Location: C:\WINDOWS\Microsoft.NET\Framework\v2.0.41101\system.dll
Codebase:
Comments
Anonymous
November 03, 2004
Hi Junfeng,
I notice you can only load 1 assembly with a given strong name using ReflectionOnlyLoad(byte[]). This is diferent to assembly Load(byte[]) where you can load as many as you like. Is this a known issue?
Am I correct in thinking that assemblies loades using ReflectionOnlyLoad will be garbage collectable? I suspect they can't be at the moment with the above behaviour.
Thanks, Jamie.Anonymous
November 04, 2004
Why would you want to choose the assembly in the GAC if I already pass the assembly using the Load(byte[]) method?Anonymous
November 04, 2004
That is by design.
Say if you do allow multiple assemblies with the same strong name loaded. Now if you need to resolve a type in the assembly with that strong name, which assembly do you want to use?
I talked in detail about ReflectionOnlyLoad here
http://blogs.msdn.com/junfeng/archive/2004/08/24/219691.aspxAnonymous
November 04, 2004
Josh,
I'll explain the reasoning later in a different blog.Anonymous
November 04, 2004
> Now if you need to resolve a type in the
> assembly with that strong name, which
> assembly do you want to use?
>
Couldn't the reflect only assembly load context be a first class object? I don't understand why the reflect only context would be bound to the app domain.
At the moment I'm using reflect only assemblies in a new app domain. I suspect going back to using Assembly.Load(byte[]) in the original app domain would be quicker.Anonymous
November 04, 2004
The comment has been removedAnonymous
November 04, 2004
Thank you for finally doing this!
I was using LoadWithPartialName to do in v1.x.Anonymous
November 05, 2004
The comment has been removedAnonymous
November 05, 2004
> You are using it to find out if a particular plug-in/addin
> implements a specific interface, right?
>
I'm actually using it to find out what assemblies my target assembly references. The configuration of the app domain the target assembly is ultimately gets loaded into depends on the referenced assemblies.
For example if the target assembly refereces 'nunit.framework', I will create an app domain configured for the NUnit test runner. If the target references 'Microsoft.VisualStudio.QualityTools.UnitTestFramework', I'll want to load an app domain configured for the Team System test runner instead.
> Why do you think Assembly.Load(byte[]) will be better?
> It pollutes the original appdomain.
>
I could have a separate app domain that was responsible for reflecting on assemblies loaded using Load(byte[]). This domain could be recycled after loading a given number of assemblies. At the moment I'm having to recycle the app domain every time I use ReflectionOnlyLoad(byte[]).
The alternative is loading the meta data tables myself. I'm only interested in any referenced assemblies, so a relatively light weight solution could work. Of cause this is a lot more complex and rather defeats the point of having a reflection only API.Anonymous
November 06, 2004
Your scenario seems perfectly fit AppDomainManager. Maybe you want to take a look there.
http://msdn2.microsoft.com/library/System.AppDomainManager.aspxAnonymous
January 21, 2009
PingBack from http://www.keyongtech.com/451881-framework-2-0-ignore-gacAnonymous
June 07, 2009
PingBack from http://greenteafatburner.info/story.php?id=1749