tags:

views:

137

answers:

4

How does .NET locate the dll of the namespace I'm using? yeah, we do mention the path in /referene:c:\program files** but after building & deploying and when the software is installed on some user's machine. It may not be at the same path as I (developer) mentioned it would be. I mean it could be some where else right?

  1. So, how does .NET find it?
  2. How does .NET know at the runtime what all namespaces are there in a dll?
  3. What if the user has the same dll but he renamed it? Does .net fails to load it then?
+2  A: 

Assembly location rules are explained in http://msdn.microsoft.com/en-us/library/yx7xezcf.aspx

CesarGon
+1  A: 

The names of assemblies and namespaces are unrelated concepts.

Compiled assembly reference other assemblies by containing their name.

When an assembly is loaded, its references are loaded by searching for the name as described here. The most common location for assemblies are the Global Assembly Cache of a machine, and the base directory of an application.

After loading the assembly and all its references (and the references of the references, etc) the runtime loads the required types from the assemblies.

For example, if you use the type String as in

using System;

...
String x = "Hello World";

the C# compiler looks up String and resolves it to the System.String type in the mscorlib assembly, and transforms the code to something similar to this:

[mscorlib]System.String x = "Hello World";

So when the statement is executed the runtime knows both the full name of the type System.String and the name of the assembly that contains the type.

dtb
Compiled assemblies can reference other assemblies by weak names, too.
Pavel Minaev
+3  A: 

Technically, there aren't any namespaces in the DLL.

On CLR level, there are no namespaces at all, only full class names. A CLR class name can consist of an arbitrarily long sequence of any Unicode characters - e.g. @#$% would be a perfectly fine class name, as far as CLR is concerned.

Now, by convention (CLS, to be specific), class names are restricted to certain Unicode characters (alphanumerics and _, and a bunch of other exotic Unicode categories - see the spec for more info) and dot, and dot is used to denote namespaces. This is purely a convention between compilers (and other tools).

So, whenever an assembly references some type for any reason, it simply uses its complete CLR name, such as System.String. But there is more - in fact, it uses a fully qualified name, which includes an assembly as well. You can see those if you look at ildasm output - they look something like [mscorlib]System.String, so the runtime knows where to look.

In other words, CLR really sees assembly mscorlib.dll having class System.String, and assembly B.exe referencing that class as [mscorlib]System.String. Your using statement doesn't generate any code in the output DLL/EXE on its own; it's there just so that you don't have to write System.String all the time.

It's compiler's job to translate your code saying String, in a scope of a using System; statement, in a project which references mscorlib.dll, to [mscorlib]System.String. It's all done at compile-time. The only thing CLR does at runtime is resolving mscorlib to locate the actual mscorlib.dll on disk (and the other answer explains how exactly that happens).

Pavel Minaev
How does it resolve from System.String to [mscorlib]System.StringHow does it know its in mscorlib assembly? System.String is quite common type. What about some custom 3rd party types. How will the compiler know in which assembly that class is located?
claws
It will look inside all assemblies referenced by the project you're compiling (or specified using `/r:` on command line). If two assemblies you reference both define a class named `System.String`, you'll get a compiler error (but you can work around that in C# using `extern alias` to disambiguate assemblies).
Pavel Minaev
"The only thing CLR does at runtime is resolving mscorlib to locate the actual mscorlib.dll on disk ." --- Say If I've installed ".NET MYSQL CONNECTOR" (using MySql.Data). Using references at compile time it detects the dll but its path will be somthing like c:\programfiles\mysql\.net\mysql.dll but after the application is built and some other is using it. all my application knows is that its this mysql.dll but on the usermachine this .net connector might be installed on d:\apps\somecrap\mysql.dll. Then how could it detect? this is what my original question is, If i was not clear.
claws
[mscorlib]System.String is it sufficent? doesn't it require strong name for this? something like [mscorlib <version> <PublicKeyToken> <Culture>] System.String
claws
You're right, it will be a strong name - in IL, other information about a referenced assembly, such as version of public key token, is specified in the assembly manifest in `.assembly extern` declaration. Regarding how it finds the assembly at run-time from a weak or strong name, Cesar's answer gives the link to the definite source on the exact rules for that. As noted by Josh, a short and simplified (and not 100% correct) answer for desktop applications is "look in GAC first, then in same directory as .exe file that started the process".
Pavel Minaev
+3  A: 

You can see the various probing steps in action if you run fuslogvw.exe (from the .NET SDK) and enable logging of all binds to disk. You will be able to see the various paths that .NET CLR uses to resolve assembly references. The rule of thumb though is to try the Global Assembly Cache first then check the local directory along with a bunch of other alternate paths.

Josh Einstein
This sounds interesting but when I started "Windows SDK tools > Fusion log viewer" every button is disabled on that window. In settings dialog also everything is disabled.
claws
If you are using Vista or Windows 7 with UAC enabled, you should run it from an elevated command prompt because it requires administrative privileges to change the fusion logging settings.
Josh Einstein
"The rule of thumb though is to try the Global Assembly Cache first then check the local directory along with a bunch of other alternate paths."Say If I've installed ".NET MYSQL CONNECTOR" (using MySql.Data). Using references at compile time it detects the dll but its path will be somthing like c:\programfiles\mysql\.net\mysql.dll but after the application is built and some other is using it. all my application knows is that its this mysql.dll but on the usermachine this .net connector might be installed on d:\apps\somecrap\mysql.dll. Then how could clr detect?
claws
Cesar posted a link to the assembly probing rules. But as I stated, the CLR will first check the Global Assembly Cache, then it will look in the local directory of the application. The fact that you referenced it from an unrelated path means nothing. Visual Studio by default sets the "copy local" attribute of these references if the assembly is not in the GAC. When you compile, Visual Studio copies that DLL to the bin directory.
Josh Einstein