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

Source: Internet
Author: User

I. Introduction

1. Introduction of the problem

Assume thatProgramIt has been deployed on your computer and can run 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,Demand spreadThe possibility 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 a script in a certain languageCode. 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. Babylon's failure[1]To some extentInformation exchangeCannot be implemented.

IV> COM components

Com[2]The emergence of the world has added a bit of vitality. OnlyInterface! 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 going to put all the core code inCspluginkernelNamespace. 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 editedDocument Object. After the program starts, enumerate every plug-in andConnectionTo the main program while passingInterface of the main program object. The plug-in can use this interfaceRequestMain ProgramObjectOr 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 the 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.

//

// This interface must be implemented by the plug-in of this Program

//

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. New Features of C --AttributeIs a good solution. Therefore, we define a class plugininfoarrti.pdf inherited from system. attribute:

///

/// Specify information about 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 serial numbers

///

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 () will returnTrue. 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.

III,Source code

Due to space limitations, please download the complete source code (including test cases) at the following link. After downloading the file, use vs. net2003 to open the file and regenerate the solution (. NET Framework 1.1 is required ). A test case is a plug-in that inserts red text into the RichTextBox Control. It is very simple and only used for testing.

 

Iv. Conclusion

That's all! With this plug-in architecture, poor programmers no longer have to worry about the spread of demand. In addition, you are welcome to evaluate this article and the additional code in this article. And, that is, always goMy blogSee ~~ Pai_^

Note:

[1] Tower of Babylon's failure: Mythical man-month,Frederick P. Brooks Jr.Chapter 4 why the tower of Babylon fails

[2] For details about COM/COM +, see mastering COM and COM +.Ash rofail, 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.