1 //------------------------------------------------------------------------------
2 // <copyright file="Component.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 namespace System.ComponentModel {
8     using System;
9     using System.ComponentModel.Design;
10     using System.ComponentModel.Design.Serialization;
11     using System.Runtime.InteropServices;
12     using System.Security.Permissions;
13 
14     /// <devdoc>
15     ///    <para>Provides the default implementation for the
16     ///    <see cref='System.ComponentModel.IComponent'/>
17     ///    interface and enables object-sharing between applications.</para>
18     /// </devdoc>
19     [
20         ComVisible(true),
21         ClassInterface(ClassInterfaceType.AutoDispatch),
22         DesignerCategory("Component")
23     ]
24     public class Component : MarshalByRefObject, IComponent {
25 
26         /// <devdoc>
27         ///    <para>Static hask key for the Disposed event. This field is read-only.</para>
28         /// </devdoc>
29         private static readonly object EventDisposed = new object();
30 
31         private ISite site;
32         private EventHandlerList events;
33 
~Component()34         ~Component() {
35             Dispose(false);
36         }
37 
38         /// <devdoc>
39         ///     This property returns true if the component is in a mode that supports
40         ///     raising events.  By default, components always support raising their events
41         ///     and therefore this method always returns true.  You can override this method
42         ///     in a deriving class and change it to return false when needed.  if the return
43         ///     value of this method is false, the EventList collection returned by the Events
44         ///     property will always return null for an event.  Events can still be added and
45         ///     removed from the collection, but retrieving them through the collection's Item
46         ///     property will always return null.
47         /// </devdoc>
48         protected virtual bool CanRaiseEvents
49         {
50             get
51             {
52                 return true;
53             }
54         }
55 
56         /// <devdoc>
57         ///     Internal API that allows the event handler list class to access the
58         ///     CanRaiseEvents property.
59         /// </devdoc>
60         internal bool CanRaiseEventsInternal
61         {
62             get
63             {
64                 return CanRaiseEvents;
65             }
66         }
67 
68         /// <devdoc>
69         ///    <para>Adds a event handler to listen to the Disposed event on the component.</para>
70         /// </devdoc>
71         [
72         Browsable(false),
73         EditorBrowsable(EditorBrowsableState.Advanced)
74         ]
75         public event EventHandler Disposed {
76             add {
77                 Events.AddHandler(EventDisposed, value);
78             }
79             remove {
80                 Events.RemoveHandler(EventDisposed, value);
81             }
82         }
83 
84         /// <devdoc>
85         ///    <para>Gets the list of event handlers that are attached to this component.</para>
86         /// </devdoc>
87         protected EventHandlerList Events {
88             get {
89                 if (events == null) {
90                     events = new EventHandlerList(this);
91                 }
92                 return events;
93             }
94         }
95 
96         /// <devdoc>
97         ///    <para>
98         ///       Gets or sets the site of the <see cref='System.ComponentModel.Component'/>
99         ///       .
100         ///    </para>
101         /// </devdoc>
102         [
103         Browsable(false),
104         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
105         ]
106         public virtual ISite Site {
107             get { return site;}
108             set { site = value;}
109         }
110 
111         /// <devdoc>
112         ///    <para>
113         ///       Disposes of the <see cref='System.ComponentModel.Component'/>
114         ///       .
115         ///    </para>
116         /// </devdoc>
117         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed")]
Dispose()118         public void Dispose() {
119             Dispose(true);
120             GC.SuppressFinalize(this);
121         }
122 
123         /// <devdoc>
124         ///    <para>
125         ///    Disposes all the resources associated with this component.
126         ///    If disposing is false then you must never touch any other
127         ///    managed objects, as they may already be finalized. When
128         ///    in this state you should dispose any native resources
129         ///    that you have a reference to.
130         ///    </para>
131         ///    <para>
132         ///    When disposing is true then you should dispose all data
133         ///    and objects you have references to. The normal implementation
134         ///    of this method would look something like:
135         ///    </para>
136         ///    <code>
137         ///    public void Dispose() {
138         ///        Dispose(true);
139         ///        GC.SuppressFinalize(this);
140         ///    }
141         ///
142         ///    protected virtual void Dispose(bool disposing) {
143         ///        if (disposing) {
144         ///            if (myobject != null) {
145         ///                myobject.Dispose();
146         ///                myobject = null;
147         ///            }
148         ///        }
149         ///        if (myhandle != IntPtr.Zero) {
150         ///            NativeMethods.Release(myhandle);
151         ///            myhandle = IntPtr.Zero;
152         ///        }
153         ///    }
154         ///
155         ///    ~MyClass() {
156         ///        Dispose(false);
157         ///    }
158         ///    </code>
159         ///    <para>
160         ///    For base classes, you should never override the Finalier (~Class in C#)
161         ///    or the Dispose method that takes no arguments, rather you should
162         ///    always override the Dispose method that takes a bool.
163         ///    </para>
164         ///    <code>
165         ///    protected override void Dispose(bool disposing) {
166         ///        if (disposing) {
167         ///            if (myobject != null) {
168         ///                myobject.Dispose();
169         ///                myobject = null;
170         ///            }
171         ///        }
172         ///        if (myhandle != IntPtr.Zero) {
173         ///            NativeMethods.Release(myhandle);
174         ///            myhandle = IntPtr.Zero;
175         ///        }
176         ///        base.Dispose(disposing);
177         ///    }
178         ///    </code>
179         /// </devdoc>
Dispose(bool disposing)180         protected virtual void Dispose(bool disposing) {
181             if (disposing) {
182                 lock(this) {
183                     if (site != null && site.Container != null) {
184                         site.Container.Remove(this);
185                     }
186                     if (events != null) {
187                         EventHandler handler = (EventHandler)events[EventDisposed];
188                         if (handler != null) handler(this, EventArgs.Empty);
189                     }
190                 }
191             }
192         }
193 
194         // Returns the component's container.
195         //
196         /// <devdoc>
197         ///    <para>
198         ///       Returns the <see cref='System.ComponentModel.IContainer'/>
199         ///       that contains the <see cref='System.ComponentModel.Component'/>
200         ///       .
201         ///    </para>
202         /// </devdoc>
203         [
204         Browsable(false),
205         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
206         ]
207         public IContainer Container {
208             get {
209                 ISite s = site;
210                 return s == null? null : s.Container;
211             }
212         }
213 
214         /// <devdoc>
215         ///    <para>
216         ///       Returns an object representing a service provided by
217         ///       the <see cref='System.ComponentModel.Component'/>
218         ///       .
219         ///    </para>
220         /// </devdoc>
GetService(Type service)221         protected virtual object GetService(Type service) {
222             ISite s = site;
223             return((s== null) ? null : s.GetService(service));
224         }
225 
226         /// <devdoc>
227         ///    <para>
228         ///       Gets a value indicating whether the <see cref='System.ComponentModel.Component'/>
229         ///       is currently in design mode.
230         ///    </para>
231         /// </devdoc>
232         [
233         Browsable(false),
234         DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
235         ]
236         protected bool DesignMode {
237             get {
238                 ISite s = site;
239                 return(s == null) ? false : s.DesignMode;
240             }
241         }
242 
243         /// <internalonly/>
244         /// <devdoc>
245         ///    <para>
246         ///       Returns a <see cref='System.String'/> containing the name of the <see cref='System.ComponentModel.Component'/> , if any. This method should not be
247         ///       overridden. For
248         ///       internal use only.
249         ///    </para>
250         /// </devdoc>
ToString()251         public override String ToString() {
252             ISite s = site;
253 
254             if (s != null)
255                 return s.Name + " [" + GetType().FullName + "]";
256             else
257                 return GetType().FullName;
258         }
259     }
260 }
261