Hello everyone, I haven't posted my post on the garden for more than half a year. I have been developing new products since I switched to a new company. Now I want to release the official version,
Is a forum software, official site is http://nt.discuz.net.
Let's just get down to the point. Some classes in the System. ComponentModel namespace were read online some time ago, mainly Component,
Container, IServceContainer, and ISite are emerging at the moment to take a good look at the relationships between these classes and how to use them, but because the available information on MSDN is not
There is plenty of information, and the search on BAINDU and GOOGLE is basically just a few words. Only a few webpages write well (basically foreigners ),
However, it focuses on the underlying logical relationship or Injection, and the instance is relatively complex or has little to do with the direction I am interested in. When reading
After being addicted, the article stops. This is indeed very depressing, there is no way, only to use reflector to reverse the code in the. NET Framework, this has some understanding,
That is, the content in today's article. This article aims to inspire others in the garden to be proficient in this aspect. If you see this article,
Please leave a few words.
The relationships between the classes mentioned above will not be much said. Apply the following online words:
The container contains components and allows them to access each other. When a container manages a component, the container is responsible for processing the component when it is disposed.
The lifetime of a component can be controlled by its container. In return for lifetime management, the component obtains access to the services provided by the container. This
The relationship is similar to the relationship between the COM + component and the COM + container that hosts it. By allowing the COM + container to manage it, the COM + component can
To participate in transactions and use other services provided by the COM + container. In the design context, the relationship between components and their containers is through the site
Created. When a component is placed in a form, the designer host creates a site instance for the component and its container. After this relationship is established, the component
It has been "site-based" and uses its ISite attribute to access the services provided by its container.
The following content focuses on Code and related comments, and is occasionally interspersed with instructions:
The container we will create is DiscuzPlugInContainer:
Public class DiscuzPlugInContainer: Container
{
Public DiscuzPlugInContainer ()
{
}
In order to customize the generated ISITE in the future, I will rewrite the CreateSite method of the Container (while the. net Framework uses an internal
The encapsulated class Site is used to create the Site. It implements the ISite and IServiceProvider interfaces. Here, DiscuzSite is a self-defined implementation.
ISITE interface class:
Public ISite CreateSite (string name, IComponent component)
{
Return CreateSite (component, name );
}
Protected override ISite CreateSite (IComponent component, string name)
{
// The code here can take over the ISIETE generated by the component that loads the container to implement our own ISITE generation method.
ISite site = base. CreateSite (component, name );
If (site = null )//
{
Site = new DiscuzSite (component, this, name );
}
Return site;
}
The DiscuzSite statement is as follows:
Class DiscuzSite: ISite
{
Private string name = "";
Private IComponent component;
Private DiscuzPlugInContainer container;
Public DiscuzSite (IComponent sitedComponent, DiscuzPlugInContainer site, string aName)
{
Component = sitedComponent;
Container = site;
Name = aName;
}
Public IComponent Component
{
Get {return component ;}
}
Public IContainer Container
{
Get {return container ;}
}
Public bool DesignMode
{
Get {return false ;}
}
Public string Name
{
Get {return name ;}
Set {name = value ;}
}
// Supports the IServiceProvider interface.
Public virtual object GetService (Type service)
{
Object s = this. container. Services. GetService (service );
If (s = null)
{
Return (object) null;
}
Return s;
}
}
The Component classes to be added to the container are directly implemented using the Inheritance Mechanism under the Component class (in fact, this is not a good practice in implementation work,
We recommend that you implement the ICompnent interface to compile your own components)
Note: The IPlugin interface here is a plug-in interface, which is added only to provide a simple example application. It needs to implement the RunPlugin Method
Public class PlugInComponent: Component, IPlugin
{
Public PlugInComponent (): base ()
{}
Public PlugInComponent (string componentName)
{
_ ComponentName = componentName;
_ InnerName = componentName;
Disposed = null;
This. Connect + = new EventHandler (this. PlugInConnect); // event customization is added here.
This. Close + = new EventHandler (this. PlugInClose); // event customization is added here.
}
The Events attribute in the Code is actually EventHandlerList events, which determines that as long as it is inherited from the component, there will be an event
. Note that. The CanRaiseEvents attribute of the Component class under the. NET Framework. Because it will only be returned if it is not overwritten.
Back to true,
As follows:
Protected virtual bool CanRaiseEvents
{
Get
{
Return true;
}
}
This provides us with some convenience in actual development work.
The user component for implementation is defined as follows. The PluginInfo here is the custom property of the user. The PlugInConnect function below is
Override of related methods in the PlugInComponent of the parent class. This is only a description of the situation, so the results will be displayed directly on the webpage.
[PluginInfo ("UserPlugin", "1.0", "daizhj", "http: // nt, discuz.net/", true)]
Class UserPlugin: PlugInComponent
{
Public UserPlugin (string componentName): base (componentName)
{
}
Public override void PlugInConnect (object sender, EventArgs e)
{
System. Web. HttpContext. Current. Response. Write ("<br>" + this. ComponentName + "user event connect ");
}
Public override void PlugInClose (object sender, EventArgs e)
{
System. Web. HttpContext. Current. Response. Write ("<br>" + this. ComponentName + "user event close ");
}
}
The following code snippet adds services and components to the container, and binds the site to the component. (Here we will replace these unrelated functions
The code is put together to illustrate the situation. If you write this code in implementation development, it will be hard to understand)
/// <Summary>
/// Component service test
/// </Summary>
Public void PluginServiceTest ()
{
// Directly add an instance to the service
This. Services. AddService (typeof (PlugMyService), new PlugMyService ());
// Use the callback method to join the service
ServiceCreatorCallback sccb = new ServiceCreatorCallback (new CallbackMySerivce (). CallBackRunMyService );
Sccb + = sccb; // because the following two components need to be created, if you want to perform ++ operations on the proxy list
This. Services. AddService (typeof (CallbackMySerivce), sccb );
PlugInComponent pic = new PlugInComponent ("daizhenjun ");
This. Add (IComponent) pic, "daizhenjun ");
ISite iss = CreateSite ("daizhenjun", (IComponent) pic );
Pic. Site = iss;
Pic. RunPlugInService (); // run related component services
This. Services. RemoveService (typeof (CallbackMySerivce); // remove the service
PlugInComponent pic1 = new PlugInComponent ("daizhenjun2 ");
This. Add (IComponent) pic1, "daizhenjun2 ");
ISite iss1 = CreateSite ("daizhenjun2", (IComponent) pic1 );
Pic1.Site = iss1;
Pic1.RunPlugInService (); // run related component services
}
Note that the ServiceCreatorCallback class is actually a delegate. The Code is as follows:
Public delegate object ServiceCreatorCallback (IServiceContainer container, Type serviceType );
I will not talk about the use and application of delegate on the Internet.
Here, the RunPlugInService function simply returns the base. GetService (service) in the base class and performs simple operations on it.
This is not recommended in actual work. (I personally think this function should be encapsulated in the service so that it can be used in components.
You can decide which services to use (CALL) based on your actual situation.
As a matter of fact, I still have some thoughts when writing the above Code:
1. If the number of sites in a Container is obtained, because the Container class in the. net Framework uses
Private int siteCount; to record, it will perform the "+ +" operation after the record is added to a component (normally added), as follows:
ISite site2 = this. CreateSite (component, name );
This. sites [this. siteCount ++] = site2;
Component. Site = site2;
Because siteCount is private, external access is not allowed. Fortunately, you can use Container. Components. Count to obtain
Exist for sites and components
.
2. However, it is difficult to obtain the number of services in the container, because the object stored in the service in ServiceContainer is a private hashtable,
The property of this field is actually private. It seems that the number of services can be counted only when the relevant code is manually written in the container.
Other Instructions (only provide a simple application scenario ):
PluginInheritTest (); // run the test by inheriting the event of the plug-in.
LoadAndRunUserComponent (); // install and run the user plug-in
The following is a reference article:
Http://www.urbanpotato.net/default.aspx/document/1757
Http://weblogs.asp.net/cazzu/archive/2004/05/10/129140.aspx
In addition, some other classes in the System. ComponentModel namespace have been described and written in the garden.
Use the sample code.
Http://www.cnblogs.com/mapserver/category/65343.html
This article is just a personal point of view. If you see it, I hope you can give suggestions or related links. Thank you.
Code download link: http://files.cnblogs.com/daizhj/Componentcode.rar
(The writing is rough, so you have to wait)