Use the C # reflection mechanism and dynamic parameters to implement the plug-in business platform

Source: Internet
Author: User

1 Introduction

In the development of information systems, changes in user business functions are unknown in advance, so it is necessary to improve business expansion in the later stages of the system. Generally, user requirements change. You need to re-compile the code, compile, produce deployment packages, and then update the user program. This process is cumbersome.

This article discusses how to dynamically bind the generated application system to the externally Compiled business database. When the application is running, it dynamically binds the external business to be implemented. When the business changes, it only replaces these external dynamic libraries and does not need to modify or compile the application again to implement coupling binding. At the same time, the business instance object can be instantiated while the program is running, achieving the encapsulation effect. It also reduces the coupling between calling code and specific implementation code, enhances flexibility and reusability, and increases Software maintainability.

C # provides the reflection mechanism, combined with the transmission of adaptive data parameters. Through this technology, we can dynamically load and construct the extension points in the application framework in the form of plug-in assembly, to implement dynamically scalable applications.

2. Basic reflection mechanism knowledge

Reflection [1] [2] is. net important mechanism, through reflection, can be obtained at runtime. net, including methods, attributes, events, and constructor. You can also obtain the name, qualifier, and parameters of each member .. The application structure of. NET is divided into application domain, assembly, module, type, and member layers. The Common Language Runtime Library loader manages the application domain, such management includes loading each assembly to the corresponding application domain and controlling the memory layout of the type hierarchy of each set. The Assembly contains modules, while the module contains types and types, and reflection provides encapsulated assembly, module, and type objects. We can use reflection to dynamically create instances of the type, bind the type to an existing object or obtain the type from the existing object, and then call the method of the type or access its fields and attributes.

Reflection usually has the following purposes: ① use assembly to define and load an assembly, load the modules listed in the assembly list, and locate the type in this Assembly and create instances of this type; ② use module to learn the following similar information, such as the Assembly of the module and the class in the module: ③ use coustructorinfo to understand the similar information as follows, for example, the name, parameter, access modifier (such as public or private) of the constructor, and implementation details (such as abstract or sha1. ④ use methodinfo to learn the similar information below, such as method name, return type, parameter, access modifier (such as public or private) and implementation details (such as abstract or sha1; ⑤ use fieldinfo to learn the following similar information, such as the field name, access modifier (such as public or private), and implementation details (such as static, and obtain or set the field value. 6. Use eventinfo to learn the following similar information, such as the event name and event location. Program Data Type, custom attribute, declaration type, and reflection type, and add or remove Event Handlers: 7. Use propertyinfo to learn the following similar information, for example, the attribute name, data type, declaration type, reflection type, and read-only or writable status, and get or set the attribute value. ⑧ uses parameterinfo to learn the following similar information, for example, the parameter name, data type, whether the parameter is an input parameter or an output parameter, and the position of the parameter in the method signature.

3. Overall Design Ideas

A plug-in is a program module written by following certain specifications of application interfaces. When the application has been deployed but the business has changed, you can read the plug-in configuration information and load new application components to implement the changed business.

For the application system framework, the extension points are pre-defined "points" in the framework ". In Framework reuse, application component assembly must be based on the extension points. Constructive and evolutionary features are two essential features of software. As an important reusable software product. Different application components can be assembled Based on the extension points to adapt to the changes in the field. It reflects the support of the Framework for Software Evolution Features [3].

This article involves several concepts: plug-in configuration definition, interface definition, method definition, call Parameter definition, and return Parameter definition. On this plug-in platform, the configuration file describes the plug-in configuration definition, interface definition, and method definition. For the call Parameter definition and return Parameter definition, the Common Object and dynamic object group [4] are used to implement incoming and return parameters.

The implementation process of the plug-in Platform 1 is shown. When the platform starts initialization, it reads xml configuration information, loads the DLL, and analyzes all implementation classes and methods in the DLL through the reflection mechanism of C. External components can be instantiated in the platform container and executed as plug-in points. The implemented algorithm is no longer hard-coded.

Figure 1 whole process of plugplatform

In this way, the application dynamically binds the external business to be implemented during the running process. When the business changes, it only replaces these external dynamic libraries and does not need to modify or compile the application again, coupling binding is implemented.

4. Specific implementation

The plugplatform platform consists of four parts: ① obtaining and parsing the configuration file; ② processing common parameters and dynamic parameter groups; ③ loading DLL on the plug-in platform and executing external methods; ④ exception handling.

4.1 obtaining and parsing configuration files

The configuration file is based on XML schema and can be divided into two types: class configuration files, which mainly describe the class and Method Content in the external DLL. The second configuration file is the interface configuration file, which mainly describes the interface and Method Content in the external DLL.

Xsd2 of the class configuration file.

Can't see the picture clearly? Click here to view the source image (large image ).

Figure 2 schema of a configuration file

Xml3 is configured according to the XSD.

Figure 3 XML tree of configuration files

Likewise, you can interface the XSD content (4) and XML tree (5) of the configuration file ).

Can't see the picture clearly? Click here to view the source image (large image ).

Figure 4 schema of the Interface Configuration File

Figure 5 XML tree of the Interface Configuration File

In the implementation of converting the data in the XML tree structure to a two-dimensional methodobject hash table, the methodobject hash table is a key-value pair of key/value, where the key is usually used for quick search, value is used to store the value corresponding to the key. The data structure of the methodobject class is as follows:

public class MethodObject {
private ClassObject classobject = null;
private InterfaceObject interfaceobject = null;
private DllFileObject dllfileobject = null;
private string name = string.Empty;
private string simplename = string.Empty;
private string implementname = string.Empty;
public string MethodName {get { return this.name; } set { this.name = value; } }
public string SimpleName { get { return this.simplename; }set { this.simplename = value; } }
public string ImplementName {get { return this.implementname; }set { this.implementname = value; }}
public ClassObject ClassObject {get { return this.classobject; }set { this.classobject = value; }}
public InterfaceObject InterfaceObject {get {return this.interfaceobject; }set {this.interfaceobject = value; }}
public DllFileObject DLLFileObject{ get { return this.dllfileobject; } set { this.dllfileobject = value; }}
}

The full name of the key in the methodobject hash table to ensure the uniqueness of the content. Yes. The primary key can be quickly searched. Value is used to store methodobject objects. Meanwhile, the methodobject object and the classobject object, interfaceobject object and dllfile object are multiple-to-one relationships. Therefore, once the methodobject object is obtained, the classobject object, interfaceobject object, and dllfile object can be reversed.

Figure 6 configure XML to methodobject hash table

Based on the XML schema, you can build an XML document tree, traverse nodes in the XML document tree hierarchically, and then convert the leaves at the edge of the XML document tree to a method object hash table using recursive algorithms, implementation Method 6 is shown in.

4.2 handling of common parameters and dynamic parameter groups

For external methods, you must input parameters and obtain results. These must be described using some common data structures. The parameter must be of any type and is a universal parameter. By creating a common data class, you can ensure that any data type is supported.

Because the number of input and output parameters is small, the parameter group must be able to automatically increase or decrease at will. You can achieve this by designing a dynamically growing parameter array. Design Model 7.

Figure 7 Design Model of datavalueobject class and dynamicarrayobject class

The method for adding an array object to a dynamic parameter group is as follows:

public DynamicArrayObject addObject(DataValueObject obj) {
if (Objects == null) {
Objects = new DataValueObject[1];
Objects[0] = obj;
return this; }
else {
DataValueObject[] objectList = new DataValueObject[Length + 1];
for (int i = 0; i < Length; i++) { objectList[i] = Objects[i]; }
objectList[Length] = obj;
Objects = objectList;
return this;}
}

The method for deleting an array object from a dynamic parameter group is as follows:

public DynamicArrayObject deleteObject(int idx) {
if (Objects == null) return this;
else {
if (idx >= 0 && idx < Length && Length > 1) {
DataValueObject[] objectList = new DataValueObject[Length - 1];
for (int i = 0; i < idx; i++) {objectList[i] = Objects[i];}
for (int i = idx + 1; i < Length; i++) {objectList[i - 1] = Objects[i]; }
Objects = objectList;
return this; }
else {
if (idx == 0 && Length <= 1) {
Objects = null;
return this; }
else return this; } }
}

4.3 plug-in platform dynamic DLL loading and execution

Plugframework is the core content of the entire plugplatform platform. It mainly checks and loads DLL files, dynamically creates instantiated objects, verifies and executes external methods.

Can't see the picture clearly? Click here to view the source image (large image ).

Figure 8 full process of plugplatform Dynamic Loading

Based on the configuration file, plugplatform can understand the mounted external DLL files and the classes or interface methods required for execution. The entire loading and calling process 8 is described.

The plugframework Contains classes and interfaces. These classes and interfaces have inheritance, implementation, and association relationships. Its Class is shown in Figure 9.

Figure 9 plugplatform class diagram

The detailed descriptions of each class of the plugframework are as follows:

Serial number

Name

Implement Functions

Remarks

1

Plus. plusconfig

The configuration information class of the plug-in platform. You can create a factory class.

Class

2

Plus. plugfactory

The factory class of the plug-in platform. You can create a method implementation class.

Class

3

Plus. iaction

Method implementation Interface

Interface

4

Plus. Framework. plugaction

Abstract ancestor class of method implementation

Class

5

Plus. Framework. classaction

Class Object implementation class

Class

6

Plus. Framework. interfaceaction

Interface object implementation class

Class

7

Plus. Framework. assemblymanager

The management class of assembly to generate assembly.

Class

8

Plus. Framework. typemanager

Type management class, which can generate and check types and objects. Including the call of dynamic methods.

Class

The core code for dynamic calling of external methods is as follows:

Public object invokeclassmethod (string classname, object [] objectargs, string methodname, object [] methodargs ){
Object [] newargs = new object [methodargs. Length];
Object thisobject = new object ();
Type type = createtype (classname );
Methodinfo [] Methods = type. getmethods ();
Object instance = Createobject (type, objectargs );
Foreach (methodinfo m in methods ){
If (M. Name = methodname ){
Newargs = convertargstype (M, methodargs );
Try {
If (! M. isstatic) thisobject = M. Invoke (instance, newargs); // non-static method called by class instance
Else thisobject = M. Invoke (null, newargs );
Return thisobject ;}
Catch (exception e) {Throw new plusexception ("the method cannot be called dynamically. Cause:" + E. Message, e );}}
}
Return thisobject;
}

Figure 10 shows the entire implementation process of plugplatform. The following describes each step in detail:

① External application requests are dynamically called.

② The plusconfig class creates a plugfactory object based on the configuration file.

③ Create an action object for the plugfactory object.

④ The Action object obtains the methodobject object group and generates the dllfileobject in reverse order.

⑤ According to the DLL file information in the dllfileobject object, the action object obtains the Assembly object through the assemblymanager class.

⑥ The Action object uses the Assembly object to create the typemanager object.

7. The action object passes the methodobject object to the typemanager object.

The categortypemanager object obtains the classobject object based on the methodobject object. And dynamically create an instance of an external classobject object using the information of the classobject object.

The ⑨ typemanager object uses instance and methodobject object information to call the dynamic method of the instance. Instance returns the execution result to the action object.

The Response Action object returns the execution result to an external application.

Can't see the picture clearly? Click here to view the source image (large image ).

Figure 10 sequence diagram of plugplatform implementation

The plus factory mode adopts the factory mode. The Singleton mode is used for the generation of assembly.

4.4 Exception Handling

Due to many unpredictable problems in the application, human errors may occur in many places on the platform, such as the failure to find the configuration file; the configuration file format is incorrect and the configuration file cannot be parsed; the class or interface name is wrong, and the class cannot be instantiated; the method name is wrong, and the method cannot be executed. Adding Exception Handling mainly enhances fault tolerance, so we will not explain it more here.

5. Application Instance

In this example, the program consists of xml configuration file, external DLL file, and plusplatform call code.

5.1 xml configuration file

There are two xml configuration files, one for class objects and the other for interface objects.

The xml configuration file of the Class Object:

<?xml version="1.0" encoding="utf-8" ?>
<PlugPlatformResource>
<DllFile name="UserLibrary.dll" filepath ="/" objectType ="class">
<classobject name="UserLibrary.UserTest1" >
<Methodobject>testAction01</Methodobject>
<Methodobject>testAction02</Methodobject>
<Methodobject>testAction03</Methodobject>
</classobject>
<classobject name="UserLibrary.UserTest2" >
<Methodobject>testAction01</Methodobject>
</classobject>
</DllFile>
</PlugPlatformResource>

The configuration file of the interface object is basically the same as the configuration file of the Class Object, except that the configuration information is changed from class to interface:

<?xml version="1.0" encoding="utf-8" ?>
<PlugPlatformResource>
<DllFile name="UserLibrary.dll" filepath ="/" objectType ="interface">
<interfaceobject name="InterfaceTest1" implement="UserLibrary.UserTest2" >
<Methodobject>testAction01</Methodobject>
</interfaceobject>
</DllFile>
</PlugPlatformResource>

5.2 DLL file content

The compiled DLL file is userlibrary. dll. The DLL file contains two classes and an interface, and its internal code is:Public class usertest1 {
Public dynamicarrayobject testaction01 (dynamicarrayobject outobject ){
Dynamicarrayobject thisobject = new dynamicarrayobject ();
// Decompose dynamicarrayobject
Datavalueobject do1 = NULL;
String ls = NULL;
For (INT I = 0; I <outobject. length; I ++ ){
Do1 = outobject. GetObject (I );
Ls + = (string) do1.getdatavalue ();}
Datavalueobject do2 = new datavalueobject ();
Do2.setdatatype (do1.getdatatype (). setdatavalue (LS );
// Assemble dynamicarrayobject and return dynamicarrayobject
Thisobject. addobject (do2 );
Return thisobject;
}
Public dynamicarrayobject testaction02 (dynamicarrayobject outobject ){
Return outobject ;}
}
Public class usertest2: interfacetest1 {
Public dynamicarrayobject testaction01 (dynamicarrayobject outobject ){
Dynamicarrayobject thisobject = new dynamicarrayobject ();
// Decompose dynamicarrayobject
Datavalueobject do1 = NULL;
String ls = NULL;
For (INT I = 0; I <outobject. length; I ++ ){
Do1 = outobject. GetObject (I );
Ls + = (string) do1.getdatavalue ();}
Datavalueobject do2 = new datavalueobject ();
Do2.setdatatype (do1.getdatatype (). setdatavalue (LS );
// Assemble dynamicarrayobject and return dynamicarrayobject
Thisobject. addobject (do2 );
Return thisobject;
}
Public dynamicarrayobject testaction02 (dynamicarrayobject outobject ){
Return outobject ;}
}
Public interface interfacetest1 {
Dynamicarrayobject testaction01 (dynamicarrayobject outobject );
}

5.3 call the plug-in platform code

There are also two types of calling code: one is for Class Object processing, and the code is as follows:

Dynamicarrayobject thisobject = new dynamicarrayobject ();
Datavalueobject do1 = new datavalueobject ();
Datavalueobject do2 = new datavalueobject ();
Do1.setdatatype ("string"). setdatavalue ("class test: first object value .");
Do2.setdatatype ("string"). setdatavalue ("second object value .");
Thisobject. addobject (do1). addobject (do2 );
String dllfile = application. startuppath + "\ dllclassfile. xml ";
Plugfactory factory = plusconfig. buildfactory (dllfile );
Iaction action = factory. creataction ();
Dynamicarrayobject outputobject = action. Execute ("userlibrary. usertest1.testaction01", thisobject );

The other is for interface object processing. The Code is as follows:

Dynamicarrayobject thisobject = new dynamicarrayobject ();
Datavalueobject do1 = new datavalueobject ();
Datavalueobject do2 = new datavalueobject ();
Do1.setdatatype ("string"). setdatavalue ("Interface Test: first object value .");
Do2.setdatatype ("string"). setdatavalue ("second object value .");
Thisobject. addobject (do1). addobject (do2 );
String dllfile = application. startuppath + "\ dllinterfacefile. xml ";
Plugfactory factory = plusconfig. buildfactory (dllfile );
Iaction action = factory. creataction ();
Dynamicarrayobject outputobject = action. Execute ("interfacetest1.testaction01", thisobject );

The returned dynamicarrayobject can be decomposed and viewed to meet the design requirements.

6. Conclusion

The reflection mechanism works well with dynamic arrays to solve the problem of post-maintenance and upgrade of application software. If the application software changes, you only need to modify the corresponding Object Name of the XML configuration file and load the new object, the program does not require any re-encoding, restart, or hard changes, and ensures the reusability of the original application system to reduce coupling and achieve reuse.

This model uses class calls and interfaces between layers and reflection mechanisms to separate callers from implementers during compilation. During runtime, the implementation class is dynamically loaded by reading the configuration file, and the implementer is forced to be transformed through the interface so that it is used by the caller to decouple the caller and the implementer. However, this function is not completely complete and there are many changes to the plug-in platform. If you can enrich the class and interface configuration files, upgrade the plug-in platform to a framework container, the container can strip the dependency between objects first, and then, when appropriate, the container is responsible for generating specific instances and injecting them into the caller. That is, the control is transferred from the application code to the external container, control has been transferred. That is, the so-called control reversal mode. This mode already has a mature framework in Java, such as spring. I believe that with Microsoft. NET's huge technical framework Platform, such a control reversal framework will also appear in C.

References

[1] (US) Karli Watson Christian Nagel and so on. Kang Bo, translated. C # entry-level classics. Beijing: Tsinghua University Press, 2006.

[2] msdn library. NET Framework developer guide: Learn type information at runtime. 2003.

[3] Liu Yu, Zhang Shiyi, Wang lifu, Yang Fuqing. Research on component-based software framework and role extension forms. Journal of software, 2004.14 (8): 1364-1370

[4] Duan yundu Lixin. C # dynamic array design principle. Computer programming skills and maintenance, 2005. (7): 24-25

[5] He Wenhai Xie Jiangang. plug-in Application Framework Development Based on. NET platform. Computer Knowledge and Technology: Academic Exchange, 2007. (8): 755-756

[6] Leng Shan Lu Han Armed Forces. Construction of Reusable Software Architecture with C #. Aviation computing technology, 2003. (4): 88-90,93

[7] Yin Kai, Xie Wenwei. Application of. Net reflection technology in the factory method model. Journal of Changzhou Institute of Technology, 2006. (4): 28-34

[8] Research and Implementation of General Software Development Platform Based on. NET. Computer Knowledge and Technology: Academic Exchange, 2007. (8): 797-798

Related Article

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.