1
votes

I am a beginner in C# and I was studying a C# text book regarding AppDomain.

This is what I found in a text book "C# 4.0 in a Nutshell 4e (O'Reilly)"

Let’s revisit the most basic multidomain scenario:

static void Main()
{
    AppDomain newDomain = AppDomain.CreateDomain ("New Domain");
    newDomain.ExecuteAssembly ("test.exe");
    AppDomain.Unload (newDomain);
}

Calling ExecuteAssembly on a separate domain is convenient but offers little opportunity to interact with the domain. It also requires that the target assembly is an executable, and it commits the caller to a single entry point. The only way to incorporate flexibility is to resort to an approach such as passing a string of arguments to the executable.
powerful approach is to use AppDomain’s DoCallBack method. This executes on another application domain, a method on a given type. The type’s assembly is automatically loaded into the domain (the CLR will know where it lives if the current domain can reference it). In the following example, a method in the currently executing class is run in a new domain:

class Program
{
    static void Main()
    {
        AppDomain newDomain = AppDomain.CreateDomain ("New Domain");
        newDomain.DoCallBack (new CrossAppDomainDelegate (SayHello));
        AppDomain.Unload (newDomain);
    }
    static void SayHello()
    {
        Console.WriteLine ("Hi from " + AppDomain.CurrentDomain.FriendlyName);
    }
}

Here, SayHello() method is present in the same Program class. By the statement,

"The type’s assembly is automatically loaded into the domain (the CLR will know where it lives if the current domain can reference it)."

This means, if SayHello() method is present in some other third party assembly, then also that assembly is loaded? I did not understand this statement. Can you please help me in this? Thank you.

2

2 Answers

0
votes

This means, if SayHello() method is present in some other third party assembly, then also that assembly is loaded?

No, it does not mean that. If we break apart the previous sentence, from the text, it will be more understandable:

This executes on another application domain, a method on a given type.

In your example the method is SayHello and the type is Program.

The type’s assembly is automatically loaded into the domain

The assembly where the type is defined will be loaded to the new application domain. This is the assembly that is built from the project that contains the Program class.

(the CLR will know where it lives if the current domain can reference it).

The CLR knows where this assembly is located because it is already loaded in your main application domain. For all loaded types it is trivial to find the location of the assembly that contains them. You have seen in the previous chapters of the book code like:

Assembly a = typeof(Program).Assembly;

or

Assembly a = anObject.GetType().Assembly;

Once you have the Assembly object you can access the Location property and get the full path to the loaded assembly.

So what this statement means is that the assembly that contains the type of the callback method will be automatically loaded to the new application domain. So this method is convenient if you want to execute code from any assembly in a new AppDomain. The drawback is that there is not much else you can do afterwards. You cannot communicate with the objects living in the new AppDomain unless you use some kind of inter-AppDomain communication such as the .NET Remoting that Hans mentions, WCF etc.

2
votes

but offers little opportunity to interact with the domain

That's entirely the point of an AppDomain. Its ability to isolate assemblies and data is the reason they exist. Every AppDomain has its own garbage collected heap and just-in-time compiled code, independent of the code and data in another AppDomain. It is an alternative over running code in a separate process, a much more performant alternative since crossing the process boundary in Windows is both difficult and expensive.

This is taken advantage of in server scenarios, SQL Server and ASP.NET being prime examples. They accept a service request from a client and execute it in a single process. The isolation gives very strong survival guarantees for the service process. If code bombs for any reason at all then the server can send back a "sorry, didn't work" response. And recover from the unhandled exception by terminating the service request thread and unloading the AppDomain, throwing away the program state that is no longer reliable. The server keeps humming as though nothing happened.

On the default CLR host, AppDomains have few practical uses but one: the ability to unload assemblies. Which permits implementing a plug-in style framework, loading and unloading code on demand. Unloading an assembly is not otherwise possible, that creates too many ways that just-in-time generated machine code can cause a crash. Having it generated inside an AppDomain permits throwing away that code and thus make unloading assemblies possible.

The price of course is that exchanging data between two AppDomains is troublesome, data has to be copied from one GC heap to another. .NET supports it well thanks to Remoting. But the data itself must have the ability to be copied across the divide, either by being [Serializable], so it can be marshaled by value, or by deriving from MarshalByRefObject, so it can be proxied.

You can further uplift the primitive example of ExecuteAssembly() by using AppDomain.Load() to load an assembly in the AppDomain and Assembly.CreateInstance() to create an object in the AppDomain. This is well covered in just about any google hits you'll find on how to support plug-ins in .NET.