application domain, you can find its definition on the Internet, all the concept of things, the people just need to search on the line, content to see on the strike, do not have to remember, not to go back, "noun interpretation" is the most boring college test the least level of questions.
Simply put, the application domain allows you to isolate some code in a process, and the same code can be executed independently in different application domains. That is, I do my thing, he does his work, do not affect each other.
First, the isolation of
Let's take a look at the isolation between application domains, and forgive the old week's low level of theory, never long-winded, the biggest feature of the old week is to write code to illustrate the problem. So, about the isolation between application domains, write code to show it.
Let's write a static class.
public static class Demo { public static string Title {get ; set ; } = <NULL> " public static string Content {get ; set ; } = <NULL> "
Experience tells us that a static member is type-based and its invocation does not need to be instantiated, so the value of a static member can generally be used globally. You should also know that at least one application domain exists in the application and is created automatically when the application is running.
Let's do a magical experiment where the results of this experiment will surprise you.
Assign a value to the static member of the static class in the application domain that the application automatically creates first.
// Assigning values in application domains that are automatically created by the application " Big Sale " ; " second-hand tofu slag commercial housing, 200 yuan a square meter. ";
OK, then, we create a new application domain, give it a name, call no Face bar.
// Create a new application domain AppDomain NewDomain = Appdomain.createdomain ("no_face");
The AppDomain has a method called DoCallback, and the invocation of the method requires a delegate as an argument, a delegate-associated method with no arguments, and a return type of void. The function of this method is to execute the code associated with the delegate in the specified application domain.
Now, we access the members of the demo static class in the newly created application domain to see what will be output.
Newdomain.docallback (() = { string msg = $"today's headline" \ n \ nthe title: { demo.title}\n text: {demo.content}"; Console.WriteLine (msg); });
After running the program, you will see the following output.
What does that mean? Indicates that the two application domains are independent, although the static type appears to be "global", but it is relative to the same application domain. As seen from the example above, assigning a static member is performed in the application domain created by the program by default, and is isolated in the newly created application domain, that is, the assignment does not exist in the new application domain, so the output is still the default value.
Ii. executing an assembly with an entry point
The AppDomain class exposes the executeassembly and ExecuteAssemblyByName methods, and the method without "name" is loaded from the file where the Assembly resides, and the method with "name" is loaded by the assembly name. As for which method to use, you look at it.
However, the assembly that calls the two methods executes must have an entry point, so it cannot be a. dll, and the class library cannot define an entry point.
Declare a class, and then remember to define the main method in the class.
Public classClass1 {Static intMain (string[] args) {Console.WriteLine ("the assembly is running in the {0} domain. ", AppDomain.CurrentDomain.FriendlyName); if(args. Length >0) {Console.WriteLine ("parameter: {0}",string. Join (",", args)); } return 0; } }
If the new project is a class library, you can open the project properties and change the project type to a Windows application.
Then, select an entry point (the type with the Main method).
Go back to the main project, create a new application domain, and then execute an assembly with an entry point.
stringFile =".. \\.. \\.. \\TestAssem\\Bin\\Debug\\TestAssem.exe"; AppDomain NEWAPPD= Appdomain.createdomain ("NEW-APPD"); intR = newappd. executeassembly (file,New string[] {"arg1","arg2","Arg3" }); Console.WriteLine ("execution result: {0}", R);
The return value of the ExecuteAssembly method is the return value of the main method to execute the assembly. Parameters can be passed to the assembly to be executed through a string array, and the parameters are propagated to the target main method.
Look at the execution results.
Three, cross-domain marshaling
Execute code in an application domain, in addition to the DoCallback method mentioned earlier, you can also use the Createinstancexxxx method, which is to directly create an instance of the execution type in the specified application domain, because the instance is routed across the application domain, it needs to be marshaled, The created instance is encapsulated in a objecthandle, and then you call the unwrap method to unpack it to get the object instance. If you want to complete this process at once, you can call a method with Anduwrap, so that it is automatically marshaled to the current application domain after the instance is created and automatically unpacked.
Using the Createinstancexxx method, it is primarily possible to transfer variables from other application domains to the current application domain, while the DoCallback method is applicable to code that can be executed independently of another application domain without referencing the variables in the current application domain.
Suppose, I define such a class.
namespace oxx{ publicclass Player { publicvoid Play () { Console.WriteLine ($" is playing on application domain" {AppDomain.CurrentDomain.FriendlyName} "). "); } }}
Then, execute it in the newly created application domain.
AppDomain NewDomain = Appdomain.createdomain ("new_face"); typeof (Oxx. Player); = (Oxx. Player) NewDomain. Createinstanceandunwrap (ObjType. Assembly.fullname, ObjType. FullName); Obj. Play ();
The code is simple, create an application domain, then create an instance of the type, and then invoke the type instance member. However, such a run is wrong because the type instance is being routed from one application domain to another, and each domain's code is isolated from each other, so the instance delivery needs to make the type serializable so that it can be copied from one application domain to another.
The first method is to add the serializable feature.
[Serializable] publicclass Player { public void Play () { } }
When this is declared, the object instance is passed by value, that is, the instance is copied from the New_face application domain to the current domain, so when you run the application, you will find that the application domain name of the output is the default application domain.
Because the instance is copied, and the play method is called in the default application domain, it outputs the current application domain name as the default domain, which is the same as the delivery of the value type, and the object itself is copied.
If you want the obj variable to execute in a new application domain, you can use the second method, which is to derive from the MarshalByRefObject class instead of using the Serializable attribute, so that reference delivery can be carried out, instead of copying a copy of the object instance's reference.
Public class Player:marshalbyrefobject { publicvoid Play () { ... } }
Now, run the example again, and discover that the output is the name of the newly created application domain, not the default domain name.
Well, this is the topic of today's discussion.
Sample source code Download
". NET deep breaths" executing assemblies across application domains