I saw someone fighting for the plug-in architecture. Article Found
In fact, if there are still e files, they will not be posted :)
In. the C # language under the. NET Framework, and other. the net language provides many powerful features and mechanisms. some of them are brand new, while others are copied from previous languages and platforms. However, this clever combination produces some interesting ways to solve our problems. This article will show you how to use these wonderful features to build scalable solutions using plug-ins. A brief example will be provided later. You can even use this to replace the independent ones that are widely used in many systems. Program . In a system, many programs often need to process data. One program may be used to process employee information, and the other to manage customer relationships. In most cases, the system is always designed as many independent programs and there is little interaction between them. replication is often used. Code But in this case, you can design those programs as plug-ins and use a single program to manage these plug-ins. This design allows us to better share public methods in different solutions and provide a unified sense.
The image is a subprogram. the user interface is no different from other common programs. the entire form is vertically divided into two parts. the left pane is a tree menu for displaying the plug-in list. The data managed by this plug-in is listed under each plug-in branch. the right pane is used to edit the data of the selected plug-in on the left. each plug-in provides its own data editing interface. image 1 shows an exquisite workspace.
Start
Then, the main program must be able to load plug-ins and then communicate with these plug-ins to achieve our design. all these implementations can be implemented in many different ways, depending only on the language and platform chosen by the developer. if C # And.. net, the reflection mechanism can be used to load the plug-in, and its interfaces and abstract classes can be used to communicate with the plug-in.
To better understand the communication between the main program and the plug-in, you can first understand the design mode. the design model was first proposed by Erich Gamma, which uses the architecture and object idea to implement a general communication model. whether or not components have different inputs and outputs, as long as they have similar structures. the design pattern can help developers solve problems using widely proved object-oriented theories. in fact, it is the language used to describe the solution, without having to worry about the specific details orProgramming LanguageDetails. the key aspect of the design pattern strategy is how to break down the entire solution based on functions. This decomposition is accomplished by separating the different functions of the main program. in this way, the communication between the main program and the subroutine can be completed through a well-designed interface. through such decomposition, we can immediately get these two benefits: first, software projects are divided into smaller irrelevant units, and workflow design can be easier, small code snippets mean that the code is easier to establish and maintain. the second advantage is that the main program will not be related to the operation of the main program when changing the program behavior. The main program does not need to care about the subprogram, as long as there is a general communication mechanism between them.
Create an Interface
In the C # program, interfaces are used to define the functions of a class. the interface defines the expected methods, attributes, and event information. to use interfaces, each specific function must complete the described functions strictly according to the interface definition. list 1 shows the interface of the above example program: iplug. this interface defines four methods: getdata, geteditcontrol, save, and print. these four definitions do not describe how they are completed, but they ensure that this class supports the iplug interface, that is, the call of these methods.
Custom Attributes
Before viewing the code, we always need to move the discussion to property customization. property customization is. one of the great new features provided by net, attributes are a common structure for all programming languages. for example, a function is used to identify the public, private, or protect attributes of the function. attribute customization is so exciting because programmers no longer have to choose from the limited Attributes provided by the language itself. A custom attribute is actually a class, which is from the system. attribute inheritance. Its code is allowed to be self-described. attribute customization can be applied to most structures, including classes, methods, events, fields, and attributes in C. the sample code snippet defines two custom attributes: plugdisplaynameattribute and plugdescriptionattribute. All classes in the plug-in must support these two attributes. list 2 is the class used to define plugdisplaynameattribute. this attribute is used to display the content of the plug-in node. when the program runs, the main program can use reflection to obtain the attribute value.
Plug-in (plug-ins)
The preceding example contains the execution of two plug-ins. These plug-ins are defined in employeeplug. CS and customerplug. cs. List 3 shows some definitions of the employeeplug class. The following are some key points.
1. this class implements the iplug interface. because the main program does not know how the class inside the plug-in is defined, it is very important that the main program uses the iplug interface to communicate with each plug-in. this design utilizes the "polymorphism" in the object-oriented concept ". polymorphism allows you to call methods in a derived class by referencing to the base class.
2. this class is identified by two attributes so that the main program can determine whether the plug-in is valid. in C #, to identify an attribute for a class, you must declare the attribute before the class definition. The content is enclosed in brackets.
3. for the sake of conciseness, the example only uses data that directly writes code. if this plug-in is a formal product, the data should always be stored in the database or file, and all the data should be managed only by the plug-in itself. the data of the employeeplug class is stored by the employeedata object here. It is also a type and implements the iplugdata interface. the iplugdata interface is in iplugdata. defined in CS, which provides the most basic data exchange function for communication between the main program and the plug-in. all objects that support the iplugdata interface provide a notification when the underlying data changes. this notification is actually the occurrence of the datachanged event.
4. when the main program needs to display the data list contained in a plug-in, it will call the getdata method. this method returns an array of iplugdata objects. in this way, the main program can use the tostring method to obtain data for each object in the array to create each node of the tree. the tostring method is an overload of the employeedata class, used to display the employee name.
5. the iplug interface also defines the SAVE and print methods. the purpose of defining these two methods is to notify a plug-in when data needs to be printed or saved. the employeeplug class is used to print and save data. when the Save method is used, the location of the data to be saved will be provided during method call. it is assumed that the main program will query the path and other information to the user. path information query is a service provided by the main program to various plug-ins. for the print method, the main program will pass the options and content to the system. drawing. printing. an instance of the printdocument class. in both cases, the interaction with the user is consistent with that provided by the main program.
Reflection (reflection)
After a plug-in is defined, the next step is to check how the main program loads the plug-in. to achieve this goal, the main program uses the reflection mechanism. reflection is.. NET is used to view the type information during runtime. with the help of the reflection mechanism, the type information will be loaded and viewed. in this way, you can check this type to determine whether the plug-in is valid. if the type is checked, the plug-in can be added to the main program interface and operated by the user.
The example program uses three built-in classes of the. NET Framework to use reflection: system. reflection. Assembly, system. type, and system. activator.
System. reflection. the Assembly class describes. net assembly. in.. net, the Assembly is the configuration unit. for a typical Windows program, the Assembly is configured as a single Win32 executable file with specific additional information to adapt it.. Net runtime environment. the Assembly can also be configured as a Win32 DLL (dynamic link library. net. system. reflection. the Assembly class can obtain assembly information during running. this information includes the type information contained in the Assembly.
System. the type class describes the type definition. A type declaration can be a class, interface, array, struct, or enumeration. after a class is loaded, system. the type class can be used to enumerate methods, properties, events, and interfaces supported by this class.
The system. activator class is used to create an instance of a class.
Load plug-ins
List 4 shows the loadplugs method. the loadplugs method is in hostform. CS is a private non-static method of the hostform class. loadplugs method usage. net reflection mechanism to load available plug-in files, verify that they meet the requirements of the main program, and then add them to the Tree display area of the main program. this method includes the following steps:
1. by using system. io. directory class. Our code can use wildcards to find all. A file with the extension of plug. the static method getfiles of Directory class can return a system. string Array to obtain the physical path of each file that meets the requirements.
2. after obtaining the path string array, you can start to load the file to system. reflection. assembly instance is in. the code that creates the asdsembly object uses the try/catch code block, so that if a file is not effective.. Net assembly, and an exception is thrown. The MessageBox dialog box is displayed, indicating that the file cannot be loaded. loop continues until all files have been traversed.
3. After an assembly is loaded, the Code traverses all accessible type information and checks whether the hostcommon. iplug interface is supported.
4. if all types support hostcommon. for the iplug interface, the Code continues to verify these types and checks whether the attributes pre-defined for the plug-in are supported. if not, a hostcommon. plugnotvalidexception type exceptions will be thrown. Similarly, the main program will pop up a MessageBox To Tell You The specific error information. loop continues until all files have been traversed.
5. finally, if these types support hostcommon. the iplug interface also defines all the attributes that need to be defined, so it will be packaged as a plugtreenode instance. this instance will be added to the Tree display area of the main program.
Implementation
The main program framework is designed as two. The first is host.exe, which provides the Windows form interface of the main program. the second assembly is hostcommon. DLL, which provides all the types required for communication between the main program and the plug-in. for example, the iplug interface is in hostcommon. DLL configuration, so that it can be accessed by the main program and plug-in equivalent. these two sets are in a folder. Similarly, the attached assembly as a plug-in needs to be configured together. the Assembly is configured in the plugs folder (A subfolders in the main program directory ). the employeeplug class is in. the plug program is defined in a centralized manner, while the customerplug class is defined in the customer. plug program centralized definition. in this example, specify the plug-in file. plug is the extension. in fact, these plug-ins are common.. Net class library file, which is usually used by library files. dll extension, used here. plug. the special extension has no effect on the running of the program, but it gives users a clearer idea that this is a plug-in file.
Design Comparison
It is not necessary to design like an example program to be correct. for example, when developing a C # program with a plug-in, you do not need to use properties. two custom attributes are used in this example. In fact, you can also define the parameters of the two iplug interfaces. attribute is selected here because the plug-in name and its description are essentially the attributes of a thing and comply with the specifications. of course, using properties will cause the main program to need more code about reflection. designers always need to make reasonable decisions for different needs.
Summary
The sample program is designed to be as simple as possible to help you understand the communication between the main program and the plug-in. In actual production, you can make many improvements to meet practical requirements. For example:
1. by adding more methods, attributes, and events to the iplug interface, you can increase the communication points between the main program and the plug-in. more interactive operations between the two allow the plug-in to do more.
2. You can select the plug-in to be loaded.
Source code
The complete source code of the sample program can be downloaded here.
Ftp://ftp.cuj.com/pub/2003/2101/walchesk.zip
Image 1:
List 1: The iplug Interface
Public interface iplug { Iplugdata [] getdata (); Plugdataeditcontrol geteditcontrol (iplugdata data ); Bool save (string path ); Bool print (printdocument document ); } |
List 2: The plugdisplaynameattribute class definition
[Attributeusage (attributetargets. Class)] Public class plugdisplaynameattribute: system. Attribute { Private string _ displayname;Public plugdisplaynameattribute (string displayname): Base () { _ Displayname = displayname; Return; } Public override string tostring () { Return _ displayname; } |
List 3: A partial listing of the employeeplug class definition
[Plugdisplayname ("employees")] [Plugdescription ("this plug is for managing employee data")] Public class employeeplug: system. Object, iplug { Public iplugdata [] getdata () { Iplugdata [] DATA = new employeedata [] { New employeedata ("Jerry", "Seinfeld ") , New employeedata ("bill", "Cosby ") , New employeedata ("Martin", "Lawrence ") };Return data; } Public plugdataeditcontrol geteditcontrol (iplugdata data) { Return new employeecontrol (employeedata) data ); } Public bool save (string path) { // Implementation not shown } Public bool print (printdocument document) { // Implementation not shown } } |
List 4: The method loadplugs
private void loadplugs () {< br> string [] files = directory. getfiles ("Plugs ","*. plug "); foreach (string F in files) { try {< br> Assembly A = assembly. loadfrom (f); system. type [] types =. gettypes (); foreach (system. type type in types) {< br> If (type. getinterface ("iplug ")! = NULL) {< br> If (type. getcustomattributes (typeof (plugdisplaynameattribute), false). length! = 1) throw new plugnotvalidexception (type, "plugdisplaynameattribute is not supported"); If (type. getcustomattributes (typeof (plugdescriptionattribute), false ). length! = 1) throw new plugnotvalidexception (type, "plugdescriptionattribute is not supported"); _ tree. nodes. add (New plugtreenode (type); }< BR >}< br> catch (exception e) {< br> MessageBox. show (E. message); }< BR >} return; } |
From: http://www.yesky.com/SoftChannel/72342380468109312/20031113/1744533.shtml