If you browse the internet, you will find the definition of Assembly as: Either an EXE (that you can execute and that has an entry point), or a DLL (you can reference it, and does not have entry point).
If you go deeper and want to know exactly what an assembly is, then you have to know the concept of a Module.
When you create an assembly, you also create a Module. An assembly by default contains one module, but you can combine multiple modules inside the same assembly.
Because multiple files (modules) can be identified as one Assembly, we can say that an assembly is the logical grouping of files.
Assemblies also are the boundary for the Internal Access Modifier. So a Class marked as internal, can be used only within the assembly.
So Assembly file contains one or more modules in addition to a special file named Manifest.
So a module is kind of the core of the assembly. If you open an assembly file and reverse it back to its intermediate language, you will see the definition of the module inside it.
Create a simple program called program.cs, then open the (Developer Command Prompt for VS2013), and browse for the project file directory, and then use the C# compiler to compile the program.cs code using (csc program.cs):
Note: You can find the developer command prompt for VS 2013 under “C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\Shortcuts“)
Now, use the ILDASM to inspect the intermediate language IL for the program.exe file , by typing :
ildasm /out:myintermediate.txt Program.exe
You can see inside the IL of the Program.EXE, that it contains a Module that is auto created for you.
You can also create a module file from a C# program like this:
csc /target:module /out:MyModuleFile.netmodule program.cs
The output file will be MuModuleFile.netmodule. You cannot use this file directory or even reference it in your project. So what can we do with it?
Create a multi-file Assembly
Open Visual Studio, and create program.cs that looks like this. Basically, it contains one class (Module1) with static public method named Hello1(). Next export this class as a module named (Module1.netmodule)
Now, rewrite the program to contain class (Module2), with one static method Hello2(). Export this class to a module named (Module2.netmodule)
Now rewrite the program as a console application, and inside the main method, call Module1.Hello1() and Module2.Hello2.
Finally, use (csc /addModule: module1.netmodule,module2.netmodule program.cs) to create one assembly that contains these files:
- Module1.netmodule (contains Hello1() method)
- Module2.netmodule (contains Hello2() method)
The main thing to remember here is that .net sees those three files as one logical file (One Assembly).
On the other hand, you can play around and create two assemblies from the three files (Module1.netmodule, Module2.netmodule, program.cs). To do that,
csc /addmodule:module1.netmodule,module2.netmodule /target:library /out:myDLL.dll
You can now reference the myDLL.dll from anywhere in your project.
Now, let us create an output assembly from the program.cs file:
csc /out:myprogram.exe program.cs
So now you have two assemblies, the myDLL.dll and the myprogram.exe file. So instead of grouping the three files to one assembly, now we made two assemblies out of the three files.
Assemblies vs Modules
As u know now, an assembly can contain one or more modules, and one module can be part of multiple assemblies. Thus an assembly is nothing but logical grouping of files, and it is the unit of access boundaries when it comes to access modifier. For example, Classes marked with Internal Access Modifiers, can be accessed within the same assembly.
DLL vs EXE Assembly
If you have a normal C# program, and you compile it once to DLL and once to EXE file, and then you use ILDASM to inspect the intermediate language, you will notice that the IL language is almost the same except for one and only one thing: the existence of a small line (.entrypoint). This is the way the intermediate language knows where to start executing the program.
Aside from this only difference, .net does not distinguish between DLL and EXE assembly files. They are the same files in IL except of the .entryline thing. The file extension (.dll or .exe) only means something to Windows, and not to .net
You can reference EXE files the same way you reference DLL files, but it is a strange way to design your project.