0% found this document useful (0 votes)
143 views21 pages

Net Frame Work

An application domain is the unit of isolation for an application in the CLR. It allows multiple applications to run in a single process while providing isolation between them. An application domain is lighter weight than a separate process. A CLR host is responsible for loading the CLR into a process and creating application domains. Assemblies contain the executable code and resources that make up an application.

Uploaded by

api-3764103
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
143 views21 pages

Net Frame Work

An application domain is the unit of isolation for an application in the CLR. It allows multiple applications to run in a single process while providing isolation between them. An application domain is lighter weight than a separate process. A CLR host is responsible for loading the CLR into a process and creating application domains. Assemblies contain the executable code and resources that make up an application.

Uploaded by

api-3764103
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 21

Questions and Answers

What is an application domain?

Application domain is a construct in the CLR that is the unit of isolation for an application. The
isolation guarantees the following:

An application can be independently stopped.

An application cannot directly access code or resources in another application.

A fault in an application cannot affect other applications.

Configuration information is scoped by application. This means that an application controls


the location from which code is loaded and the version of the code that is loaded.

For more information see COM+ Application Domains.

What is the difference between an application domain and a


process?

An application domain is lighter than a process. Application domains are appropriate for scenarios
that require isolation without the heavy cost associated with running an application within a
process. A process runs exactly one application. In contrast, the CLR allows multiple applications
to be run in a single process by loading them into separate application domains. Additionally, the
CLR verifies that user code in an application domain is type safe.

For more information see COM+ Application Domains.

What is a CLR host?

The Windows operating system does not provide support for running a CLR application. That
support is provided by a CLR host. A CLR host is an application that is responsible for loading the
CLR into a process, creating application domains within the process, and executing user code
within the application domains. Examples of hosts that ship with the .NET Framework include:

ASP.NET. An ISAPI filter that ships with ASP.NET loads the CLR and does the initialization
necessary to handle web requests.

Internet Explorer. A MIME filter hooks into Internet Explorer versions 5.01 and higher to
execute managed controls referenced from HTML pages.

Shell Executables. When a managed application is launched from a shell, a small piece of
unmanaged code loads the CLR and transitions control of the application to the CLR.
For more information see Hosting the Common Language Runtime.

What is a default domain?

The default domain is an application domain that is created automatically by the CLR every time it
is initialized in a process. The default domain is not unloaded until the process shuts down. Most
hosts dont run code in the default domain for two main reasons. First, the default domain cannot
be shut down independently of the process. Second, for security and isolation reasons, it is
desirable that the user code and hosting code execute in different application domains. Instead,
hosts create application domains with a set of properties that control security, isolation, loading,
etc.

What is an assembly?

An assembly is a reusable, versionable, self-describing deployment unit for types and resources it
is the primary building block of a .NET application. Assemblies provide the infrastructure to allow
the runtime to fully understand the contents of an application and to enforce the versioning and
dependency rules defined by the application.

An assembly consists of the following two logical elements:

The sets of types and resources that form some logical unit of functionality.

A manifest which is the metadata that describes how the types and resources relate and
what they depend on to work properly.

For more information see Assembly Overview.

How do I run managed code in a process?

The first step in running managed code in a process is to get the CLR loaded and initialized using
a CLR host. Typically, a host consists of both managed code and unmanaged code. The
managed code which executes in the default domain is usually responsible for creating the
application domains in which the user code exists. All CLR hosts must contain unmanaged code
because execution must begin in unmanaged code. The .NET Frameworks provides a set of
unmanaged APIs that the host can use to configure the CLR, load the CLR into a process, load
the hosts managed code into the default domain, and transition from the unmanaged code to the
managed code.

The second step in running managed code in a process is to create application domains in which
the user code will execute. The creator of the application domain can specify criteria which
control code isolation, security, and loading of assemblies.

The third step in running managed code in a process is to execute user code in one or more
application domains created in the previous step. All code that is run in the CLR must be part of
an assembly. There are three options for loading assemblies. First, precompiled assemblies can
be loaded from disk. Second, precompiled assemblies can be loaded from an array of bytes.
Third, assemblies can be built dynamically in an application domain using the BCL Reflection
Emit APIs.

Note. For an application launched from the command-line, the shell host executes the steps
described above on behalf of the user and hides the complexity from the user.

For more information see Hosting the Common Language Runtime.

What is the purpose of the System._AppDomain interface?

The System._AppDomain interface is meant for use by unmanaged code that needs access to
the members of the managed System.AppDomain class. Unmanaged code calls the methods of
the System._AppDomain interface through COM Interop. Unmanaged code can obtain a pointer
to the _AppDomain interface by calling QueryInterface on the default domain. See Hosting the
Common Language Runtime and Common Language Runtime Hosting Interfaces for details.

How do I create an application domain?

The default domain is created automatically when a CLR hosts unmanaged code calls the CLR
hosting interface to load the CLR.

A user application domain is created by calling one of the following overloaded static methods of
the System.AppDomain class:

1. public static AppDomain CreateDomain(String friendlyName)

2. public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo)

3. public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo,


AppDomainSetup info)

4. public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo, String


appBasePath, String appRelativeSearchPath, bool shadowCopyFiles)

Overload 1 allows an application domain to be created given its name. Overloads 2-3 allow a
System.Security.Policy.Evidence object to be supplied to CreateDomain to define the security
policy for the application. Overload 3 allows a System.AppDomainSetup object to be supplied to
CreateDomain to configure how assemblies are loaded into the application domain. Overload 4
allows some of the common configuration settings to be specified as parameters without defining
a System.AppDomainSetup object.

How do I configure how assemblies are loaded into an application


domain?
An application domain is configured by supplying a System.AppDomainSetup object to the
following static method of the System.AppDomain class:

public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo,


AppDomainSetup info)

The AppDomainSetup class provides a set of properties that can be set or retrieved. The
properties control how assemblies are loaded into an application domain. The most important
properties are ApplicationBase and ConfigurationFile. The other properties are used mainly by
a CLR host and are described in the BCL documentation. A newly created application domain
inherits the ApplicationBase property of its creator. No other property is inherited by the new
application domain.

The ApplicationBase property defines the root directory for an application. When an assembly
needs to be loaded from the disk, the CLR will begin probing for the assembly in the directory
specified by the ApplicationBase property. This provides a degree of isolation in that the
assemblies that are loaded are privatized to a particular application.

The ConfigurationFile property defines the XML file that contains the configuration settings for the
application that executes in the application domain. The configuration file describes information
such as versioning rules and policies for locating types. For more information see Configuration
Files for the CLR.

The following code snippet creates an application domain with default security policy and specific
ApplicationBase and ConfigurationFile properties:

// C# Sample Code

using System;

AppDomainSetup info = new AppDomainSetup();

info.ApplicationBase = C:\\Program Files\\MyApp;

info.ConfigurationFile = C:\\Program Files\\MyApp\\MyApp.exe.config;

AppDomain appDomain = AppDomain.CreateDomain(MyDomain, null, info);

How do I retrieve configuration information about an an application


domain?

Use the following property of the System.AppDomain class.

public AppDomainSetup SetupInformation { get; }


How do I define the security policy for an application domain?

The runtime enforces code-access security. In code-access security, what code is allowed to do is
based on the characteristics of the code called Evidence. The runtime maps the evidence to a
set of permissions when the code is loaded and run. The permissions control specific actions of
the code.

A host can control policy in two ways:

First, the host can provide evidence to an application domain when it is created by supplying an
Evidence object to System.AppDomain.CreateDomain. This supplied evidence is added to the
evidence for the code before the security policy for the code is evaluated. For example, the
following code snippet restricts code running in an application domain associated with a Web site
to no more permissions than code originating from the site:

// C# Sample Code

using System;

using System.Security.Policy;

Evidence evidence = new Evidence();

Evidence.AddHost(new URL(http:://www.site.com);

AppDomain appDomain = AppDomain.CreateDomain(MyDomain, evidence);

Second, the host can restrict the permissions granted at a specific policy level. The hierarchy of
policy levels beginning at the top level are: enterprise wide policy, machine wide policy, per user
policy, and application domain level policy. Each policy level can restrict the permissions granted
by the level above it. The System.AppDomain.SetAppDomainPolicy is used to specify security
policy. For more information and an example of how to use the method, see Hosting the Common
Language Runtime.

How do I retrieve the evidence for an application domain?

Use the following property of the System.AppDomain class.

public Evidence Evidence { get; }

How do I execute an application in a remote application domain?

The System.AppDomain class provides the following methods that can be used to run an
assembly in an application domain:
1. public int ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

2. public int ExecuteAssembly(String assemblyFile, Evidence assemblySecurity)

3. public int ExecuteAssembly(String assemblyFile)

Overload 1 is the most general form of ExecuteAssembly. The first parameter is the path name of
the assembly to be executed. The second parameter allows the caller to supply a
System.Security.Policy.Evidence object for the assembly. The last parameter allows the caller
to supply an array of parameters to be passed to main entry point of the assembly.

The steps necessary to execute an assembly in a remote application domain are as follows:

Create the remote application domain using System.AppDomain.CreateDomain. Optionally


specify the following:

o Configuration information such as ApplicationBase to control where assemblies are


searched for during loading.

o Evidence to control specific actions of the code executed in the application domain.

Execute the assembly using System.AppDomain.ExecuteAssembly on the application


domain created in the previous step.

Note that the ExecuteAssembly method will not work with executables generated by Visual C++
compiler due to the way the unmanaged CRT startup works.

The following code snippet shows how to execute an assembly named HelloWorld1:

// C# Sample Code

// File: ExecAssembly.cs

// Creates a remote application domain and executes an assembly

// within that application domain.

using System;

using System.Reflection;

using System.Runtime.Remoting;
public class ExecAssembly

public static void Main( String[] argv )

// Set ApplicationBase to the current directory

AppDomainSetup info = new AppDomainSetup();

info.ApplicationBase = "file:///" + System.Environment.CurrentDirectory;

// Create an application domain with null evidence

AppDomain dom = AppDomain.CreateDomain("RemoteDomain", null, info);

// Tell the AppDomain to execute the assembly

dom.ExecuteAssembly("HelloWorld1.exe");

// Clean up by unloading the application domain

AppDomain.Unload(dom);

The HelloWorld1 assembly contains the following code:

// C# Sample Code

// File: HelloWorld1.cs

using System;

using System.Threading;

public class HelloWorld


{

public void SayHello(String greeting)

Console.WriteLine("In the application domain: " + Thread.GetDomain().FriendlyName);

Console.WriteLine(greeting);

public static void Main( String[] argv )

HelloWorld o = new HelloWorld();

o.SayHello("Hello World!");

Compile ExecAssemby.cs and HelloWorld1.cs as follows:

csc ExecAssembly.cs

csc HelloWorld1.cs

How do I invoke a method in a remote application domain?

The steps necessary to invoke a method in a remote application domain are as follows:

Create the remote application domain using System.AppDomain.CreateDomain. Optionally


specify the following:

o Configuration information such as ApplicationBase to control where assemblies are


searched for during loading.

o Evidence to control specific actions of the code executed in the application domain.
Ensure the type containing the method to be invoked derives from
System.MarshalByRefObject. This is necessary to ensure that the type is marshaled by reference
across the boundary of the created application domain.

Call System.AppDomain.CreateInstance to create an instance of the parent type of the


method in the application domain created in the previous step. CreateInstance will return a
wrapped object reference (ObjectHandle) that needs to be unwrapped before it can be used.

Unwrap the ObjectHandle to obtain an Object reference to invoke methods on the type.

The System.AppDomain class provides the following methods for instantiating a type:

1. public ObjectHandle CreateInstance(String assemblyName, String typeName)

2. public ObjectHandle CreateInstance(String assemblyName, String typeName, Object[]


activationAttributes)

3. public ObjectHandle CreateInstance(String assemblyName, String typeName, bool


ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes, Evidence securityAttributes)

4. public ObjectHandle CreateInstanceFrom(String assemblyFile, String typeName)

5. public ObjectHandle CreateInstanceFrom(String assemblyFile, String typeName, Object[]


activationAttributes)

6. public ObjectHandle CreateInstanceFrom(String assemblyFile, String typeName, bool


ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes, Evidence securityAttributes)

The difference between CreateInstance and CreateInstanceFrom is that CreateInstances first


parameter is the simple name of an assembly while the first parameter to CreateInstanceFrom is
the path name of the assembly. The first method calls the static method Assembly.Load while the
second method calls the static method Assembly.LoadFrom. See loading of assemblies for
additional details.

The System.AppDomain class also provides the following convenience methods that combine the
operations of instantiating a type and unwrapping the ObjectHandle:

1. public Object CreateInstanceAndUnwrap(String assemblyName, String typeName)

2. public Object CreateInstance(String assemblyName, String typeName, Object[]


activationAttributes)
3. public Object CreateInstance(String assemblyName, String typeName, bool ignoreCase,
BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes, Evidence securityAttributes)

4. public Object CreateInstanceFromAndUnwrap (String assemblyFile, String typeName)

5. public Object CreateInstanceFromAndUnwrap (String assemblyFile, String typeName,


Object[] activationAttributes)

6. public Object CreateInstanceFromAndUnwrap (String assemblyFile, String typeName, bool


ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes, Evidence securityAttributes)

The following code snippet shows how to invoke the SayHello method in the HelloWorld2
assembly:

// C# Sample Code

// File: Invoke.cs

// Creates a remote application domain and invokes a method

// within an assembly in that application domain.

using System;

using System.Reflection;

using System.Runtime.Remoting;

public class InvokeMethod

public static void Main( String[] argv )

// Set ApplicationBase to the current directory

AppDomainSetup info = new AppDomainSetup();

info.ApplicationBase = "file:///" + System.Environment.CurrentDirectory;


// Create an application domain with null evidence

AppDomain dom = AppDomain.CreateDomain("RemoteDomain", null, info);

// Load the assembly HelloWorld2 and instantiate the type

// HelloWorld

BindingFlags flags = (BindingFlags.Public | BindingFlags.Instance |


BindingFlags.CreateInstance);

ObjectHandle objh = dom.CreateInstance("HelloWorld2", "HelloWorld", false, flags, null, new


String[]{"Hello World!"}, null, null, null);

if (objh == null) {

Console.WriteLine("CreateInstance failed");

return;

// Unwrap the object

Object obj = objh.Unwrap();

// Cast to the actual type

HelloWorld h = (HelloWorld)obj;

// Invoke the method

h.SayHello();

// Clean up by unloading the application domain

AppDomain.Unload(dom);
}

The HelloWorld2 assembly contains the following code:

// C# Sample Code

// File: HelloWorld2.cs

using System;

using System.Threading;

public class HelloWorld : MarshalByRefObject

private String _greeting;

public HelloWorld(String greeting)

if (greeting == null) {

throw new ArgumentNullException("Null greeting!");

_greeting = greeting;

public void SayHello()

Console.WriteLine("In the application domain: " + Thread.GetDomain().FriendlyName);

Console.WriteLine(_greeting);
}

Compile Invoke.cs and HelloWorld2.cs as follows:

csc /t:library HelloWorld2.cs

csc /r:Helloworld2.exe Invoke.cs

Note. The HelloWorld2 assembly must be locatable in the callers application domain and the
remote application domain. The assembly is loaded into the remote application domain by
CreateInstance. It is loaded into the callers application domain when the Object obj is cast to the
HelloWorld type.

Note. If the metadata for the invoked method SayHello is not available in the callers application
domain, you may get errors during JIT compilation.

How do I load an assembly into an application domain?

The System.AppDomain and the System.Reflection.Assembly classes provide many overloads


for loading an assembly into an application domain. The System.AppDomain.Load methods are
primarily meant for COM Interoperability use. However, they can be used safely to load an
assembly into the current application domain.

An attempt to call AppDomain.Load on an application domain that is not the current application
domain will result in a successful load of the assembly in the target application domain. Since
Assembly objects are not MarshalByRef, when the method attempts to return the Assembly
object for the loaded assembly to the current application domain (i.e., the callers application
domain), the runtime will try to load the specified assembly into the current application domain.
The load may fail if the configuration settings (such as AppDomainSetup.ApplicationBase) for the
two application domains are different. Even when the loading into the current application domain
succeeds, the Assembly object that is loaded into the current application domain is different from
the assembly that was loaded into the target application domain.

The System.AppDomain provides the following methods for loading an assembly into an
application domain:

1. public Assembly Load(AssemblyName assemblyRef)

2. public Assembly Load(AssemblyName assemblyRef, Evidence evidence)

3. public Assembly Load(AssemblyName assemblyRef, Evidence evidence, String


callerLocation)
4. public Assembly Load(byte[] rawAssembly)

5. public Assembly Load(byte[] rawAssembly, byte[] rawAssemblyStore)

6. public Assembly Load(byte[] rawAssembly, byte[] rawAssemblyStore, Evidence evidence)

7. public Assembly Load(String assemblyName)

8. public Assembly Load(String assemblyName, Evidence evidence)

9. public Assembly Load(String assemblyName, Evidence evidence, String callerLocation)

Note. Overloads 3 and 9 are obsolete and will be removed in a future release.

Overloads 1-3 require the caller to supply an System.Reflection.AssemblyName object that


specifies what assembly is to be loaded. See the description of the class in the BCL reference
documentation for the details. Overload 2, 6, and 8 allow the caller to supply evidence for the
assembly code that will execute in the application domain. Overloads 4-6 are used to load a
COFF-based image containing an emitted assembly and optionally specify the raw bytes
representing the symbols for the assembly. In overloads 7-9, the assemblyName parameter
should be an assembly name and not the path or filename of the requested assembly.
assemblyName does not include an extension such as .DLL or .EXE.

Some examples of AssemblyName include the following:

A simply named assembly with a default culture:

com.microsoft.crypto, Culture=

A fully specified reference for strong named assembly with culture en:

com.microsoft.crypto, Culture=en, PublicKeyToken=a5d015c7d5a0b012, Version=1.0.0.0

Partially specified AssemblyName which may be satisfied by either strong or simply named
assembly:

com.microsoft.crypto

com.microsoft.crypto, Culture=""

com.microsoft.crypto, Culture=en

The System.Reflection.Assembly class provides the following static methods for loading an
assembly into the current application domain:
1. public static Assembly Load(AssemblyName assemblyRef)

2. public static Assembly Load(AssemblyName assemblyRef, Evidence evidence)

3. public static Assembly Load(AssemblyName assemblyRef, Evidence evidence, String


callerLocation)

4. public static Assembly Load(byte[] rawAssembly)

5. public static Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore)

6. public static Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore, Evidence evidence)

7. public static Assembly Load(String assemblyName)

8. public static Assembly Load(String assemblyName, Evidence evidence)

9. public static Assembly Load(String assemblyName, Evidence evidence, String


callerLocation)

10.public static Assembly LoadFrom(String assemblyFile)

11.public static Assembly LoadFrom(String assemblyFile, Evidence evidence)

Note. Overloads 3 and 9 are obsolete and will be removed in a future release. Overload 1-9 of
Assembly.Load are similar to the overloads 1-9 of AppDomain.Load with the difference that the
static Assembly.Load methods load the specified assembly into the current application domain
while the instance AppDomain.Load methods load the specified assembly into the target
application domain. The same restriction on the assemblyName parameter that applied to
AppDomain.Load also applies to overloads 7-9, i.e., the assembly name should not be a path
name or a file name of the requested assembly and should not contain an extension such as .DLL
or .EXE in the name. Overloads 10-11 can be used to load an assembly from a specific location
by specifying a file name or path to the assembly.

Note. To ensure that assemblies loaded using Assembly.LoadFrom do not interfere with direct
dependencies of the managed application (obtained using Assembly.Load), the assembly cache
manager maintains separate load contexts, namely, a default load context and a LoadFrom
load context. The default load context records the assembly name and assembly instance
information of the transitive closure of dependent assembies that are directly used by the
managed application. The LoadFrom load context contains the assembly name and assembly
instance information for all assemblies loaded using Assembly.LoadFrom as well as the transitive
closure of their dependencies. For more information about load contexts, consult the SDK
documentation.
Note. The System.AppDomain class does not provide LoadFrom methods similar to the
System.Assembly.LoadFrom methods. If you wish to load an assembly into a target application
domain given a file name fro an assembly, you will need to use the following workaround:

Create a stub assembly that calls System.Assembly.LoadFrom using the file name of the
assembly to be loaded into the target application domain.

Execute the stub assembly in the target application domain using


System.AppDomain.ExecuteAssembly.

How do I dynamically resolve assemblies, types, and resources?

The assembly resolution is controlled by the configuration properties for the application domain
such as System.AppDomainSetup.ApplicationBase. The configuration properties may not be
sufficient in some hosting scenarios, especially if the host is creating assemblies in memory on
the fly using Reflection Emit, since there may not be an assembly on disk to find. In such cases,
you can use the System.AssemblyResolve event to hook into the type loading process.

The AssemblyResolve event is defined as follows:

public event ResolveEventHandler AssemblyResolve

where System.ResolveEventHandler is defined as follows:

public delegate Assembly ResolveEventHandler(Object sender, ResolveEventArgs args)

The args parameter to ResolveEventHandler is the identity of the assembly the runtime is
seeking. The receipient of the event is free to resolve the reference to the assembly by any
means. For example, the receipient may construct an assembly on the fly, find it in a custom
location on disk, etc. The only requirement is that the receipient return a instance of
System.Reflection.Assembly.

The following sample code shows how to define a handler to resolve an assembly dynamically:

// C# Sample Code

// File AssemblyResolve.cs

// Illustrates how to resolve an assembly dynamically.

using System;

using System.Reflection;

using System.Reflection.Emit;
using System.Runtime.Remoting;

using System.Threading;

public class AssemblyResolve

// This method invokes the "SayHello" method on the

// type "HelloWorld" of an assemby "DynamicHelloWorld".

// The assembly does not exist on the disk but is created

// on the fly by the assembly resolution handler.

public static void Main( String[] argv )

// Define the handler for resolving the assembly

AssemblyResolve assemblyResolve = new AssemblyResolve();

ResolveEventHandler hndlr = new


ResolveEventHandler(assemblyResolve.AssemblyResolver);

AppDomain dom = Thread.GetDomain();

dom.AssemblyResolve += hndlr;

// Attempt to load the assembly. This should trigger the

// handler when the assembly is not found on disk.

// Load the assembly HelloWorld

Assembly asm = Assembly.Load("DynamicHelloWorld");

if (asm == null) {
Console.WriteLine("Main: Can't load assembly HelloWorld");

return;

// Lookup the type in the loaded assembly

Type t = asm.GetType("HelloWorld");

if (t == null) {

Console.WriteLine("Main: Can't find type HelloWorld");

return;

// Instantiate the type HelloWorld

Object o = Activator.CreateInstance(t, null);

// Use Reflection, to invoke the "SayHello" method

t.InvokeMember("SayHello", BindingFlags.Public | BindingFlags.Instance |


BindingFlags.InvokeMethod, null, o, null);

// The handler uses Reflection Emit to dynamically build

// the "DynamicHelloWorld" assembly with the type "HelloWorld"

public Assembly AssemblyResolver(Object sender, ResolveEventArgs args)

{
// Write message that we are in the assembly resolver

Console.WriteLine("AssemblyResolver: Building assembly" + args.Name + "...");

// Define the dynamic assembly

AssemblyName asmName = new AssemblyName();

asmName.Name = "DynamicHelloWorld";

AssemblyBuilder asm = Thread.GetDomain().DefineDynamicAssembly(asmName,


AssemblyBuilderAccess.Run);

// Define a dynamic module in the assembly

ModuleBuilder mod = asm.DefineDynamicModule("DynamicHelloWorld");

// Define the "HelloWorld" type in the module

TypeBuilder typ = mod.DefineType("HelloWorld", TypeAttributes.Public);

// Define the "SayHello" method

MethodBuilder meth = typ.DefineMethod("SayHello", MethodAttributes.Public, null, null);

ILGenerator il = meth.GetILGenerator();

il.EmitWriteLine("Hello World!");

il.Emit(OpCodes.Ret);

// Complete the type and return the dynamic assembly

typ.CreateType();
Console.WriteLine("Returning dynamic assembly");

return asm;

Compile AssemblyResolve.cs as follows:

csc AssemblyResolve.cs

A type is resolved dynamically by defining a handler for the TypeResolve event. The
TypeResolve event is defined as follows:

public event ResolveEventHandler TypeResolve

A resource is resolved dynamically by defining a handler for the ResourceResolve event. The
ResourceResolve event is defined as follows:

public event ResolveEventHandler ResourceResolve

For both types and resources, the handler must resolve the assembly in which the entity is
defined. The code for the handler is very similar to the handler shown in the sample above.

How do I unload an assembly?

CLR does not provide a way to unload an assembly. The only mechanism to remove the
assembly is to unload the application domain in which the assembly is loaded. If you wish to
remove an assembly after it has been used, you should create an application domain, load the
assembly into the created application domain, and then unload the application domain when you
no longer need the assembly.

How do I unload an application domain?

You should use the following static method in the System.AppDomain class:

public static void Unload(AppDomain domain)

The Unload method gracefully shuts down the specified application domain. During shutdown no
new threads are allowed to enter the application domain and all application domain specific data
structures are freed. You cannot unload an application domain in a finalizer or destructor.
If the application domain has run code from a domain-neutral assembly, the domains copy of the
statics and related CLR data structures are freed, but the code for the domain-neutral assembly
remains until the process is shutdown. There is no mechanism to fully unload a domain-neutral
assembly other than shutting down the process.

You might also like