C # Plug-in Architecture Practice (Jack H Hansen)

Source: Internet
Author: User

I. Introduction

1. Introduction of the problem

Assume that the program you designed has been deployed on your computer and runs properly. But one day, the user called and asked for new features. After determining the user's requirements, you can find that the original software architecture is no longer qualified for new tasks-you need to redesign this application! But the problem is that even if you use another development cycle to complete the applications required by the user, there is no guarantee that the user's requirements will not change again. That is to say, the possibility of spreading demand still exists. Therefore, in this case, the plug-in architecture can better demonstrate its superiority.

2. Comparison of several solutions

I have summarized the plug-in architecture I have come into use, which can be roughly divided into the following categories:

I> script

Write the program logic of the plug-in into script code in a certain language. This language can be Python or other existing script languages that have been tested by users for a long time. You can even design a scripting language to meet your special needs. Of course, using the most popular XML today is no longer appropriate.

This form features that users with a little programming knowledge can modify your script on their own (pai_^ if you do not encrypt it ). We cannot argue whether this is good or bad. Because the consequences of this situation are unpredictable.

Ii> dynamic function library DLL

Plug-in functions exist in the form of dynamic library functions. The main program uses some channel (plug-in writer or some tools) to obtain the function signature in the plug-in DLL, and then calls them in the appropriate place. Readers who have used Matlab know that almost all functions of Matlab are dynamic chained functions.

Iii> Aggregation

As the name implies, the plug-in function is directly written as EXE. In addition to fulfilling your responsibilities, the main program is also responsible for scheduling these "ins ". I don't like this form. This makes it much more difficult to exchange information between plug-ins and between the main program and plug-ins. The failure of the Babylon tower [1] is, to some extent, caused by the inability of information exchange.

Iv> COM components

The emergence of COM [2] has added some vigor to the world. Only interfaces are available! All we need to do is implement the interface defined by the program. The main program does not need to know how the plug-in can implement predefined functions. It only needs to access the plug-in through interfaces and provide interfaces for the objects related to the main program. In this way, information exchange between the main program and various plug-ins becomes very simple. In addition, the plug-in is completely transparent to the main program.

3. Decision-making

C # is an object-oriented programming language. It provides interface keywords to directly define interfaces. At the same time, the System. Reflection namespace also provides a series of related objects to access the external assembly. This laid a solid foundation for implementing the plug-in Architecture in C.

Next, we will take a program editor with a plug-in architecture as an example to illustrate the implementation of this architecture in C.

Ii. Design Process

Now we are ready to put all the core code in the CSPluginKernel namespace. Use VSIDE to create a C # class library project. Start our code in the namespace CSPluginKernel.

1. Interface Design

Our program editor will open the document objects being edited to the plug-in. After the program starts, enumerate each plug-in, connect it to the main program, and pass the interface of the main program object. The plug-in can use this interface to request the main program object or access the main program function.

Based on the above requirements, we first need a main program interface:

Public interface IApplicationObject {

Void Alert (string msg); // generates a message

Void ShowInStatusBar (string msg); // display the specified information in the status bar

IDocumentObject QueryCurrentDocument (); // obtain the currently used Document Object

IDocumentObject [] QueryDocuments (); // obtain all document objects // set the event Processor

Void SetDelegate (Delegates whichOne, EventHandler targer );

} // Currently only this event is required

Public enum Delegates {Delegate_ActiveDocumentChanged ,}
Then the IDocumentObject interface. The plug-in accesses the editor object through this interface.

//// The editor object must implement this interface ///

Public interface IDocumentObject {// these attributes are corresponding property ing of the RichTextBox Control

String SelectionText {get; set ;}

Color SelectionColor {get; set ;}

Font SelectionFont {get; set ;}

Int SelectionStart {get; set ;}

Int SelectionLength {get; set ;}

String SelectionRTF {get; set ;}

Bool HasChanges {get ;}

Void Select (int start, int length );

Void AppendText (string str );

Void SaveFile (string fileName );

Void SaveFile ();

Void OpenFile (string fileName );

Void CloseFile ();

}
This interface does not need to be explained too much. Here I only implement a few methods of the RichTextBox Control. For other methods that may be used, add them as needed.

Then, design the interface of the plug-in based on the behavior of the plug-in its lifecycle.

///// The plug-in of this program must implement this interface ///

Public interface IPlugin {

ConnectionResult Connect (IApplicationObject app );

Void OnDestory (); void OnLoad (); void Run ();

}

///// Indicates the connection result between the plug-in and the main program ///

Public enum ConnectionResult {Connection_Success, Connection_Failed}
The main program will first call the Connect () method and pass the IApplicationObject to the plug-in. The plug-in performs initialization in this process. Then, the OnLoad () method of the plug-in is called. After that, when the main program receives a signal to call the plug-in (keyboard, mouse response), it will call the plug-in's Run () method to start the plug-in. The OnDestory () method is called when the program ends. In this way, the life of the plug-in ends.

2. Storage and acquisition of plug-in information

A plug-in must have its name, version, and other information. As a designer, you must also leave your distinguished name and personal website to promote yourself. C #'s new feature-attribute is a good solution. Therefore, we define a class plugininfoarrti.pdf inherited from System. Attribute:

///// Specify the relevant information of a plug-in ///

Public class PluginInfoAttribute: System. Attribute {

//// Deprecated. Do not use .///

Public PluginInfoAttribute (){}

Public PluginInfoAttribute (string name, string version, string author, string webpage, bool loadWhenStart) {// The details are omitted}

Public string Name {get {return _ Name ;}}

Public string Version {get {return _ Version ;}}

Public string Author {get {return _ Author ;}}

Public string Webpage {get {return _ Webpage ;}}

Public bool LoadWhenStart {get {return _ LoadWhenStart ;}}

///// Used to store some useful information ///

Public object Tag {get {return _ Tag;} set {_ Tag = value ;}}

/// // Used to store the serial number ///

Public int Index {get {return _ Index;} set {_ Index = value ;}}

Private string _ Name = "";

Private string _ Version = "";

Private string _ Author = "";

Private string _ Webpage = "";

Private object _ Tag = null;

Private int _ Index = 0; // temporarily unavailable

Private bool _ LoadWhenStart = true;

}
Use this class to modify your plug-in and enable it to implement the IPlugin interface:

///// My Pluging 1 (Just for test )///

[PluginInfo ("My Pluging 1 (Just for test)", "1.0", "Jack H Hansen", "http://blog.csdn.net/matrix2003b", true)]

Public class MyPlugin1: IPlugin {public MyPlugin1 (){}

# Region IPlugin member // The details are omitted

# Endregion

Private IApplicationObject _ App;

Private IDocumentObject _ CurDoc;

}

3. Load the plug-in

Now we need to use the System. Refelction namespace. When the program starts, it searches for every file in the plugins directory. For each file, if it is a plug-in, it is loaded with an Assembly object. Then enumerate every object in the Assembly. The method to determine whether an assembly is our plug-in is to determine whether it directly or indirectly implements self-IPlugin. Use the following function to pass the System. Type of the object enumerated from the Assembly.

Private bool IsValidPlugin (Type t ){

Bool ret = false;

Type [] interfaces = t. GetInterfaces ();

Foreach (Type theInterface in interfaces ){

If (theInterface. FullName = "CSPluginKernel. IPlugin ")

{Ret = true; break ;}

} Return ret;

}
If all the conditions are met, IsValidPlugin () returns true. Then the program creates this object and stores it in an ArrayList.

Plugins. Add (pluginAssembly. CreateInstance (plugingType. FullName ));
Now you can write the test code.

Note:

[1] The failure of the tower of Babylon, the mythical man-month, Frederick P. Brooks Jr. Chapter 7th: Why does the tower of Babylon fail

[2] For details about COM/COM +, see Mastering COM and COM +, Ash Rofail, and Yasser Shohoud.

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.