Unity3d API and limitations for dynamically loading DLLs

Source: Internet
Author: User

Unity3d's Pit series: Dynamically loading DLLs

I. Limitation OF USE

Now participating in the project is to do MMO hand tour, the target platform is Android and Ios,ios platform can not dynamically load DLL (what reason to find jobs to go), can directly ignore, and on the Android platform can be dynamically loaded DLL, with this can implement code updates, but in fact, There are a lot of restrictions on how to load DLLs dynamically in unity (not knowing the words are pits).

Limit 1: In Android dynamically loaded DLLs in your phone cannot use Assembly.loadfile (string path), only use Assembly.Load (byte[] rawassembly) This interface, so you have to find a way to read it first.

Limit 2: Dynamically loaded scripts cannot be hung on prefab in the editor.

Limit 3: If the script is called in a dynamic DLL, call AddComponent () on prefab on this script without using addcomponent ("Somescript"), use AddComponent (Type.GetType (" Somescript ")).

Limit 4: Using [Requirecomponent (typeof (Somescript))] In a dynamic DLL is not valid, so it cannot be used.

I am mainly encountering these pits at present, and then I will add some new discoveries. the Windows LoadFile () test is possible.

Fix & Add: In iOS not all cannot dynamically load DLL, jailbreak mobile phone can be implemented, specific reference article: http://blog.csdn.net/lucky_06/article/details/9093879, pro-Test no problem.

Fix it again: iOS still can't actually implement the real code hot update, using the above method can only invoke external DLL interface, but the execution logic is inside native code. Simply put, before I test the project has a.dll code, and then Assembly.Load A.dll come in, call A.dll inside the method is possible, but actually called the code in the project, if there is no a.dll code in the project, the call will error, above.

Second, C # reflection knowledge and API

Some of the knowledge about C # Reflection is estimated to be up to the extent of using the API, as far as it is difficult to get a deeper understanding of the current level of estimation, so the following article, as a summary of the phase.

For the summary of reflection, I want to start with a reflection assembly, a module, a member of the class, and some information about the member, and then the member method of the dynamic invocation class, and the third aspect of dynamically generating assemblies, modules and classes, and members of the class. Okay, now let's start by reflecting all sorts of information.

In C #, we want to use reflection, first to understand the relationships of several classes in the following namespaces:

System.Reflection namespaces

(1) AppDomain: An application domain that can be understood as a logical container for a set of assemblies

(2) Assembly: assembly class

(3) Module: Modular class

(4) Type: The most core class for using reflection to get type information

There is a dependency between them, that is, an AppDomain can contain N assembly, a assembly can contain n module, and a module can contain n type.

The AppDomain is a class we'll explain later. Let's focus on assembly classes first.

In the program, what if we want to load an assembly dynamically? There are several ways to use it, namely, load, LoadFrom, and loadwithpartialname three assembly static methods.

To explain the Assembly.Load method, the method will have multiple overloaded versions, one of which is to provide the details of the Assembly, that is, the identity of the Assembly, including the assembly name, version, zone information, public key token, all provided as a string, for example: " myassembly,version=1.0.0.0,culture=zh-cn,publickeytoken=47887f89771bc57f ".

So what is the order of loading assemblies using Assembly.Load? First it goes to the global assembly cache lookup, then to the application's root directory, and finally to the application's private path lookup.

Of course, if you are using a weakly named assembly, which gives you only the name of the assembly, then at this point the CLR will not apply any security or deployment policies on the assembly, and load will not find the assembly in the global cache assembly.

Examples of tests that load weakly named assemblies are as follows:

(1) Create a new console Application project, and check the creation of a solution

(2) Create a new class library project in the solution, write a class and a method casually

(3) In the console project, first do not add a reference, directly in the main method to add the following code:

Assembly Assembly = Assembly.Load ("myassembly");

if (assembly! = null)

{Console.WriteLine ("Load Succeeded");}

Executes the program and throws an exception saying that the assembly could not be found. What's the reason? Because we are using a weakly named assembly, the Load method does not look in the global assembly cache, and the application directory does not have the assembly, so the program cannot find it. At this time, we change the program a little bit, without adding code, just add a reference to MyAssembly, rerun the program, loaded successfully.

Next, we'll look at how load loads the strong-named assembly, which is a little bit more complicated. Or just the project, find the directory where the MyAssembly.dll assembly is located, usually in the bin "debug directory

(1) Generate key pair file Sn–k Myassemblykey.keys

You can do it yourself. A key pair file name

(2) Generate a public key file

Sn–p Myassemblykey.keys Myassemblypublickey.publickey

Note: View public key command: SN–TP Myassemblypublickey.publickey

(3) Create a strong-named assembly.

Simply add the following feature to the code that declares the namespace:

[Assembly:assemblykeyfileattribute (@ "D:" Test "Myassemblykey.keys")]

(4) Compile the project

(5) Add an assembly to the Assembly global cache

Gacutil–i MyAssembly.dll

At this point, go to the project that loads the assembly, change the parameters in the Load method to "assembly name, version= version, culture= zone information, publickeytoken= public key", and then remove the reference to the Assembly, and we will find that the program runs successfully. Indicates that the load has found the assembly in the global cache.

Using the Load method to load assemblies, especially strong-named assemblies, to apply security and deployment policies on assemblies, it is recommended to use this method to load assemblies dynamically, as for LoadFrom and LoadWithPartialName.

First, let's take a look at the LoadFrom method, the principle of which is this: if we want to use it to dynamically load an assembly, we must tell it the path of the Assembly, that is, under which directory the CLR will load an assembly that exactly matches the path you specify. Remember, when we specify the assembly path, we cannot include any information about the strong naming of the assembly, so the CLR does not apply any policy on the assembly file that we specify, and does not go anywhere else to search for the assembly, in short, it refers to where to hit, hehe.

For example: You have an assembly in D:/test/myassembly.dll, you want to load the assembly with Assembly.LoadFrom, the code is as follows:

Assembly Assembly = Assembly.LoadFrom (@ "D:/test/myassembly.dll");

For the Loadwithparitalname method, it is recommended that you do not use it because the program cannot determine which assembly version is ultimately going to be loaded, so here's just a brief introduction to how it works: You can pass an assembly ID to it, including the assembly name, As for other information is optional (area information, public key, etc.), when the method executes, it first checks the qualifyassembly node of the configuration file in the application, and if so, replaces the assembly of that part name with the full assembly identity, if it does not exist, Use the assembly name to look in the application root, then the private directory, and find it in the assembly global cache if it is not found. The simple process is as follows:

Assembly global Cache, application Private directory, application root directory.

The difference between the Assembly.Load () method, the Assembly.LoadFrom () method, the Assembly.loadfile () Method!

1,assembly.load ()

This method loads the assembly through the long name of the assembly (including assembly name, version information, language culture, public key token), loads the other assemblies referenced by this assembly, and generally should take precedence over this method, which is much more efficient than LoadFrom. And does not cause the problem of repeated loading (the reason is explained on the 2nd)

With this method, the CLR applies a certain policy to find the assembly, in effect the CLR locates the Assembly in the following order:

⑴ If the assembly has a strong name, first look for the Assembly in the global Assembly Ease (GAC).

⑵ if the strong name of the assembly is not specified correctly or is not found in the GAC, the URL specified by the <codebase> element in the configuration file is searched for

⑶ If a strong name is not specified or cannot be found in the GAC, the CLR probes for a specific folder:

Assuming that your application directory is a privatepath in the c:/appdir,<probing> element that specifies a path Path1 the assembly you are targeting is AssemblyName.dll, the CLR will locate the assembly in the following order

C:/appdir/assemblyname.dll

C:/appdir/assemblyname/assemblyname.dll

C:/appdir/path1/assemblyname.dll

C:/appdir/path1/assemblyname/assemblyname.dll

If the above method cannot find the assembly, a compilation error occurs, and if the assembly is loaded dynamically, an exception will be thrown at run time!

2,assembly.loadfrom ()

This method loads the assembly from the specified path, and when the method is actually called, the CLR opens the file, gets the assembly version, language culture, public key token, and so on, passes them to the Load method, and then the Load method uses the above policy to find the assembly. If an assembly is found, it is compared to the path specified in the LoadFrom method, and if the path is the same, the Assembly is considered part of the application, and if the path is different or the Load method does not find the assembly, the Assembly is simply loaded as a "data file". is not considered part of the application. This is why the load method mentioned in the 1th is more efficient than the LoadFrom method. In addition, because the assembly may be loaded as a "data file", loading the same assembly from different paths with LoadFrom causes a duplicate load. Of course, this method will load other assemblies referenced by this assembly.

3,assembly.loadfile ()

This method loads the assembly from the specified file and differs from the method above in that the method does not load other assemblies referenced by this assembly!

Conclusion: In general, you should choose the Load method to load the assembly, if you encounter the need to use the LoadFrom method, it is best to change the design and use the Load method instead!

Another: The difference between Assembly.loadfile and Assembly.LoadFrom

1, assembly.loadfile only load the corresponding DLL file, such as Assembly.loadfile ("Abc.dll"), then load Abc.dll, if Abc.dll is referenced def.dll, Def.dll will not be loaded.

Assembly.LoadFrom is not the same, it loads the DLL file and other DLLs it references, such as the example above, Def.dll will also be loaded.

2, when loading a assembly with Assembly.LoadFrom, will first check whether the front has been loaded with the same name assembly, such as Abc.dll has two versions (version 1 under directory 1, version 2 is placed under directory 2), the program was initially loaded in version 1, When loading version 2 o'clock with Assembly.LoadFrom ("2//abc.dll"), it cannot be loaded, but instead returns version 1. Assembly.loadfile will not do such a check, such as the above example to Assembly.loadfile, then the correct loading version 2.

LoadFile: Loads the contents of the assembly file on the specified path. LoadFrom: Loads the contents of the assembly file based on the file name of the assembly.

Difference:

The LoadFile method is used to load and check assemblies that have the same identity but are located in different paths. But the program's dependencies are not loaded.

LoadFrom cannot be used to load an assembly that identifies the same but has a different path.

Unity3d API and limitations for dynamically loading DLLs

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.