Directory
Nineth Chapter plug-in engine design ... 2
9.1 Framework of the contract-interface ... 2
9.2 The prototype of the plugin-abstract class ... 3
9.3 Implementation Interface ... 4
9.4 Reflection Mechanism ... 5
9.5 Reflection Tool Class ... 8
9.6 Summary ... 9
Nineth Chapter plug-in engine design
In the introduction of the 10th chapter of the host program detailed design of the interface and plug-in the relevant content of the overall introduction, in the design of the host program will use this knowledge, but also the host program and plug-in interaction between the core content.
9.1 Contract of the framework-interface
After the host program of the plug-in framework starts, it will first load the corresponding configuration file (for example: Device driver configuration file, etc.), find the corresponding plug-in assembly, these assemblies exist in the DLL file format, the framework's host program will find the specified plug-in type, The plug-in engine generates an object instance based on the plug-in type (for example: Irundevice), which is managed and dispatched by the manager of the framework's host program.
A plug-in assembly may include multiple plug-in types, how does the framework host program recognize that these types are plug-ins to be loaded? Each plug-in object has an identity-interface, which is called a "communication contract" in the framework design. Interfaces can be thought of as a collection of methods, properties, and events that define the necessary, so that the host program can generate concrete instance objects and expose actionable objects to other components or interfaces.
The plug-in framework acts as a high-aggregation, low-coupling platform, and its functional definition is separated from the functional implementation. As long as the two development components that conform to the plug-in specification can be mounted to the framework platform, it is not in the mind of the specific functions of these components. Of course, the framework platform provides the necessary information, mechanisms to ensure that these components can normally achieve two development functions.
In the structure design with multiple logical levels, the communication between the layers is mostly realized through the interface, the interface will not change easily, if the function of one layer changes, it will not affect the other layers, so long as the component function of the interface is implemented properly, the operation of the program will be no problem. This approach minimizes the interaction between the layers, in short, the interface is better decoupled in a multi-service hierarchy.
In most functional programming and design work, it is seldom necessary to consider the "Interface (interface)" Case, if we only meet the way the control is programmed on the IDE and use the generic class library in the. NET framework, the interface may never be used in the program, even in C # In the object-oriented language, the reader will see the word countless times, but also to complete the general function, not mastering the core idea of object-oriented programming.
Interfaces are definitions and contracts for general behavior. Animals, such as cats and dogs, only need to define general, public properties, actions, etc. in the interface, such as: Have Eyes, can eat things and so on. Although there are significant differences between animals, the interface does not take into account the differences in their characteristics or functions, such as: what color of the eye, what to eat, etc. It only cares that these types all have to implement all the functions of the interface definition, and implementing this interface can be regarded as an animal.
Therefore, the two main functions of an interface are:
n defines the public methods, properties, that are required for multiple types.
n exists as a type that cannot be instantiated.
The methods, properties, and so on, which inherit the interface implementation, are actually implementing a strategy.
9.2 The prototype of the plugin-abstract class
Interfaces are very similar to abstract classes, for example, both cannot be new to an instance object, but can be
is used for a contract and definition. But interfaces and abstract classes are fundamentally different, and these differences include:
The N interface does not have any implementation parts, but the abstract class can inherit the partial implementation code after the interface.
n interfaces have no fields, but abstract classes can contain fields.
n interfaces can be inherited by structures (structs), but not by abstract classes.
N Abstract classes have constructors and destructors.
n interfaces can inherit only from interfaces, whereas abstract classes can inherit from other classes and interfaces.
n Interfaces support multiple inheritance, and abstract classes support only single inheritance.
The following recommendations on interfaces and abstract classes are given in the relevant content of MSDN:
n If you expect to create multiple versions of a component, create an abstract class. Abstract classes provide a simple way to control the component version. By updating the base class, all inherited classes are automatically updated with the changes. On the other hand, the interface cannot be changed once it is created, and a completely new interface must be created if the version of the interface is to be updated.
N if the created feature will be used across a wide range of heterogeneous objects, the interface is used. Abstract classes should be used primarily for closely related objects, and interfaces are best suited to provide common functionality for unrelated classes.
n If you want to design a small and concise function module, you should use an interface. If you are designing large functional units, you should use an abstract class.
n If you want to provide common implemented functionality across all implementations of a component, you should use an abstract class. Abstract classes allow partial implementations of classes, and interfaces do not contain implementations of any members.
9.3 Implementing the interface
Both interfaces and abstract classes can be used as "communication contracts" to provide specifications for subclasses. The following defines an interface and an abstract class.
Defines an interface public interface imyinterface{ void Action (int type); string Method (int para);} Defines an abstract class public abstract class baseabstract:imyinterface{public abstract void Action (int type); This method must be implemented when inheriting such abstract classes. Public string Method (int para) //Implement this approach { return para. ToString (); }}
To inherit an interface, you need to implement all of the defined methods or properties, such as the following code:
public class myclass1:imyinterface{public void Action (int type) { Console.WriteLine (type). ToString ()); } public string Method (int para) { return para. ToString (); }}
To inherit an abstract class, you only need to implement methods or properties that are not implemented by an abstract class, typically abstract methods or properties, such as the following code:
public class myclass2:baseabstract{public void Action (int type) //Inherit abstract class, just implement this function. { Console.WriteLine (type. ToString ());} }
9.4 Reflection mechanism
With a device driver or plug-in, it cannot be mounted to the host program of the framework platform. The question we are considering is that there are already any number of types of plug-in assemblies, how does the framework platform generate plug-in objects in memory from an assembly based on type definitions?
Review the process of normal cases in which the program references other assembly components. First, you need to use the Add Reference dialog box to load the assembly. The namespace is then referenced through the Using keyword. Finally, the corresponding class is found under the command space, and a new instance is created. This is a way of statically loading assemblies.
In a plug-in application framework, this approach is not appropriate. The host program does not know at compile time which assemblies it will handle, and there is no way to statically introduce plug-in types through the Using keyword, which is information that is available at run time. In such cases, it is also not possible to use static methods and the new keyword to generate a type instance. Instead, you need to get relevant information at run time to load the assembly dynamically, a process known as reflection.
Reflection is a capability to dynamically discover type information, which is similar to late binding, helping developers to use the assembly information dynamically using types when the program is running, which is unknown at compile time, and reflects support for more advanced behavior, such as the ability to dynamically create new types at run time, and invoke methods of these types.
When the JIT compiler compiles the IL code to the cost code, it looks at those types that are referenced in the IL code. At run time, the JIT compiler leverages the TypeRef of the Assembly and the record entries of the AssemblyRef metadata table to determine which assembly defines the type of the reference. Various parts of the assembly strong name are recorded in the AssemblyRef metadata record entry-including name, version, public key token, and language culture. These four sections make up a string identifier. The JIT compiler attempts to load an assembly that matches this identity into the current AppDomain. If the assembly is weakly named, only the name will be included in the identity.
In the. NET framework, for dynamic loading, you need to familiarize yourself with the methods of tools classes such as assembly, type, and Activator. The framework platform mainly uses the Assembly tool class, which includes load, LoadFrom, and LoadFile.
1. Assembly 's Load method
The internal CLR uses the assembly load method to load the assembly, which is equivalent to the Loadlibray of the Win32. Internally, load causes the CLR to apply a version redirection policy to an assembly. and find the assembly in the GAC, if it is not found, go to the application's base directory, the private path directory, and the codebase specified location to find it. If it is a weakly named assembly, load does not apply a redirection policy to the Assembly, nor does it go to the GAC to find the assembly. If a reference is found that returns a assembly, the FileNotFoundException exception is thrown if it is not found. Note: The load method will simply return a reference to the assembly if it has already loaded an assembly with the same identity, rather than creating a new assembly.
In most dynamically extensible applications, the assembly load method is the preferred way for assemblies to load into the AppDomain. This way you need to specify an identity string for the assembly. For weakly named assemblies, specify only one name.
2 . The LoadFrom method of Assembly
When we know the path of the assembly, you can use the LoadFrom method, which allows passing in a path string, internally, LoadFrom first calls the AssemblyName static method GetAssemblyName. This method opens the specified file, extracts the assembly's identity through the AssemblyRef metadata table, and then closes the file. Subsequently, LoadFrom calls the assembly's Load method internally to find the assembly. Here, his behavior is consistent with the Load method. The only difference is that if the assembly is not found by load, LoadFrom loads the assembly specified by the path. In addition, path can be a URL.
3.Assembly the LoadFile Method
This method looks very much like the LoadFrom method. However, the LoadFile method does not internally invoke the assembly load method. It only loads the assembly of the specified path, and this method can load the assembly from any path, and the same assembly, if it is under a different path, is allowed to be loaded multiple times, equal to multiple assemblies with the same name loaded into the AppDomain, which is completely distinct from the two methods above. However, LoadFile does not load the assembly's dependencies, that is, other assemblies that do not load the assembly reference, which causes the runtime to find exceptions for other reference DLLs. To resolve this issue, you need to enlist the Assemblyresolve event to the AppDomain and display the loaded referenced assembly in the callback method. Similar to this:
AppDomain.CurrentDomain.AssemblyResolve + = new Resolveeventhandler (currentdomain_assemblyresolve); static Assembly Currentdomain_assemblyresolve (object sender, Resolveeventargs args) { if (args. Name = null) { return Assembly.LoadFrom (string. Format ("{0}\\plugin\\{1}.dll", Application.startuppath, New AssemblyName (args). Name). Name)); } return null;}
Special note: To test whether LoadFile has loaded the referenced DLL, you must not copy the DLL to the root of the application test, because that directory is the default directory for the CLR to load the assembly, and in this directory, if there is a referenced DLL, it will be loaded, Causes LoadFile to load the illusion of referencing DLLs. You can create a new subdirectory under the root directory, such as plugin, to copy the referenced DLL to this side for testing.
The reflection mechanism also has its drawbacks: security and performance aspects. However, the framework platform needs to use reflection when it starts up and adds new device drivers (plug-ins), and once loaded into the host program, there is no essential difference between the static reference assembly, which is in memory.
9.5 Reflection Tool Class
The plug-in framework platform is driven by a reflection mounted device and runs in the host program, requiring a dedicated tool class to complete the function. The code is defined as follows:
<summary>///a lightweight Iobjectbuilder implementation//</summary>public class typecreator:iobjectbuilder{Public T buildup<t> () where T:new () {return activator.createinstance<t> (); } Public T buildup<t> (string typeName) {return (T) activator.createinstance (Type.GetType (Ty Pename)); } public T buildup<t> (object[] args) {Object result = Activator.CreateInstance (typeof (T), a RGS); return (T) result; }///<summary>///framework platform mainly uses this function. </summary>//<typeparam name= "T" ></typeparam>//<param name= "AssemblyName" >< ;/param>//<param name= "instancename" ></param>///<returns></returns> Publ IC T buildup<t> (String assemblyname, string instancename) {if (! System.IO.File.Exists (AssemblyName)) {thRow New FileNotFoundException (AssemblyName + "does not exist"); } System.Reflection.Assembly assmble = System.Reflection.Assembly.LoadFrom (AssemblyName); Object tmpobj = assmble. CreateInstance (instancename); Return (T) tmpobj; } Public T buildup<t> (string typeName, object[] args) {Object result = Activator.createins Tance (Type.GetType (typeName), args); return (T) result; }}9.6 Summary
The next section describes the host program's detailed design, requires a certain understanding of the reflection mechanism, and uses the above tool class, and expands on that basis.
The framework platform is going to be complete, just one small step.
Only laugh at
Email:[email protected]
qq:504547114
. NET Development Technology Alliance: 54256083
Document Download: Http://pan.baidu.com/s/1pJ7lZWf
Official website: http://www.bmpj.net
[Serial] "C # communication (Serial and network) framework design and implementation"-9. Plug-in engine design