In order to give you a better understanding of the plug-in, let's first review the process of creating and calling the DLL under normal circumstances.
Every programmer knows that we should compile some classes or modules into DLL and then call them in the main program. I will not be so embarrassed about the purpose and benefits of doing so.
Suppose I have created a class library named TirayComm. dll and compiled a UDP class for UDP data transmission:
Namespace Tiray. Net
{
Public class UDP
{
...
// Port -- local listening port
// Ttl time, in milliseconds
Public UDP (int port, short ttl)
{
...
}
// Initialization
Public void Init ()
{
...
}
// Send data
// Data -- data to be sent
// RemoteIP -- remote IP Address
// Port -- remote UDP port
Public void Send (byte [] data, string remoteIP, int port)
{
...
}
// Close
Public void Close ()
{
...
}
}
}
The following code creates a UDP-type instance in the main program and calls a UDP-type method:
Using Tiray. Net
...
Tiray. Net. UDP udp = new UDP (25000,2000 );
Udp. Int ();
...
Do not forget to add a reference to TirayComm. dll in the project.
I would like to remind you that the above steps are completed in your IDE, that is, they are completed in the process of writing program code.
Next I will explain in detail some technical details about implementing plug-ins using C # using a software project I developed previously.
I have received an SP software project to develop a text message interaction platform for a radio station. In the demand analysis process, I realized that the SMS interaction platform of the radio station needed flexible function expansion, because a radio station often has several frequencies, and each frequency is an average of a different program every hour, each program may have different requirements on the SMS platform: Some programs only require the SMS platform to display the audience's SMS to the host; some programs require the SMS platform to automatically reply to certain information; some programs, such as text message answering, require the text messaging platform to automatically determine whether the user's answer is correct and provide the lucky draw function ...... the worst thing is that even for the same program, its content may be changed or revised at any time, and new requirements on the SMS platform will be put forward.
At this time, I started to have the idea of writing plug-ins. I hope that when the host asks for a new text message application, I only need to write a plug-in to implement the relevant application logic, and then install the plug-in a specific directory of the text message platform, you can implement the corresponding functions without upgrading the entire SMS platform. Similarly, when the host no longer needs a text message application, I simply need to delete the corresponding plug-in from a specific directory.
The following is the base class of the plug-in I wrote. Note that this is an abstract class. In the plug-in sense, two common abstract methods and an event are the interface standard definition of the plug-in. I didn't use the interface keyword to define the interface of the plug-in, because I still have some Code related to the SMS gateway that needs to be implemented in this class, I also don't want to consider implementing multi-inheritance in the plug-in. In fact, you can also use the interface keyword to define the interface of the plug-in. For more information about abstract classes and interfaces, go to MSDN.
Namespace Tiray. SMS
{
Public abstract class Plugin
{
// Plug-in name
Protected String pluginName;
...
// OnReceive is the event processing function after receiving SMS messages from CMPP30 of China Mobile SMS gateway and SGIP of China Unicom SMS Gateway
// DestNumber -- number of the SP end, such as 1066123456
// PhoneNumber -- mobile phone number, such as 13812345678
// Message -- Short Message
Public abstract void OnReceive (String destNumber, String phoneNumber, String message );
// Display plug-in attributes. You can call this method to view and set plug-in attributes.
Public abstract void ShowProperty ();
...
// Processing function when the plug-in instance is destroyed from the memory.
Public abstract void Finalize ();
...
// Plug-in events
// A short message request is usually sent.
Public event PluginEventHandler PluginEvent;
}
// Plug-in event Definition
Public delegate void PluginEventHandler (object sender, PluginEventArgs e );
}
The following is a text message plug-in for traffic programs to query traffic violations. The function of this plug-in is to return the traffic violation records of the license plate number within a period of time when the user sends a license plate number to the SMS interactive platform. This plug-in is compiled into a class library named Illegal. dll and then published to the "Plugin" subdirectory of the main program.
Using Tiray. SMS;
Namespace Tiray. SMS. RadioService
{
// Traffic violation query text message plug-in
Public class IllegalQuery: Plugin
{
...
Public IllegalQuery ()
{
...
PluginName = "traffic violation query ";
...
}
Public override void ShowProperty ()
{
...
}
Public override void Finalize ()
{
...
}
Public override void OnReceive (String destNumber, String phoneNumber, String message)
{
...
// Check and process the license plate number
String carNumber = CheckCarNumber (string message );
If (carNumber! = String. Empty)
{
...
// Query and send illegal records to the user's mobile phone
QueryAndSend (carNumber, phoneNumber );
...
}
...
}
}
}
From the code above, I just implemented a very common class inheritance, and it seems that the plug-in has something different. Next let's take a look at how the plug-in is called in the main program.
...
Using Tiray. SMS;
Using System. Reflection;
...
...
Protected Hashtable n_htPlugin = null;
...
Protected void InitPlugin ()
{
M_htPlugin = new Hashtable ();
String dir = Directory. GetCurrentDirectory () + @ "\ plugin ";
String [] files = Directory. GetFiles (strDir, "*. DLL ");
Foreach (string file in files)
{
Tiray. SMS. Plugin plugin = null;
Try
{
System. Reflection. Assembly asm = System. Reflection. Assembly. LoadFile (files );
Type [] types = asm. GetTypes ();
Foreach (Type type in types)
{
If (type. BaseType. FullName = "Tiray. SMS. Plugin ")
{
Plugin = asm. CreateInstance (type. FullName) as Plugin;
Break;
}
}
}
Catch (Exception ex)
{
...
Plugin = null;
...
}
If (plugin! = Null)
{
Plugin. PluginEvent + = new PluginEventHandler (OnPlugin );
M_htPlugin.Add (plugin. Name, plugin );
}
}
}
// Messages from the plug-in
// A short message request is usually sent.
Protected void OnPlugin (object sender, PluginEventArgs e)
{
...
}
}
Note that the plug-in instance is created using the CreateInstance method of the Sytem. Reflection. Assembly class. Compared with the UDP instance creation method I mentioned earlier, I did not add references to Illegal. DLL in the main program, nor did I directly declare the IllegalQuery class in the program.
In the previous lecture, I mentioned that one of the advantages of the plug-in is the Function Extension during runtime. Through the code above, you should have some knowledge about this feature of the plug-in.
The above is just a simple example, but as you can see, in order to implement the plug-in, I have to add more code in the main program, for example, I have created a Hashtable to store every plug-in instance in the memory. I have used more code to create a plug-in instance than the conventional class instance creation method; although I did not list the code of the plug-in event processing function, I can imagine that I must use more code to determine which plug-in triggered the current event. In fact, some more complicated issues need to be considered for the implementation of the plug-in. In the third section, I will further discuss the plug-in.
Now, let's review the two basic features and implementation methods of the plug-in:
Unified Call Interface
This is achieved by defining an abstract class with the abstract keyword or using the interface keyword to define an interface;
Load at runtime
This is implemented using the related methods of the System. Reflection. Assembly class.