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