Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / ComponentModel / COM2Interop / COM2Properties.cs / 1305376 / COM2Properties.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms.ComponentModel.Com2Interop { using System.Runtime.Remoting; using System.Runtime.InteropServices; using System.ComponentModel; using System.Diagnostics; using System; using System.Collections; using System.Collections.Generic; using Microsoft.Win32; ////// /// This class is responsible for managing a set or properties for a native object. It determines /// when the properties need to be refreshed, and owns the extended handlers for those properties. /// internal class Com2Properties { private static TraceSwitch DbgCom2PropertiesSwitch = new TraceSwitch("DbgCom2Properties", "Com2Properties: debug Com2 properties manager"); ////// /// This is the interval that we'll hold props for. If someone doesn't touch an object /// for this amount of time, we'll dump the properties from our cache. /// /// 5 minutes -- ticks are 1/10,000,000th of a second /// private static long AGE_THRESHHOLD = (long)(10000000L * 60L * 5L); ////// /// This is the object that gave us the properties. We hold a WeakRef so we don't addref the object. /// internal WeakReference weakObjRef; ////// /// This is our list of properties. /// private Com2PropertyDescriptor[] props; ////// /// The index of the default property /// private int defaultIndex = -1; ////// /// The timestamp of the last operation on this property manager, usually /// when the property list was fetched. /// private long touchedTime; ////// For non-IProvideMultipleClassInfo ITypeInfos, this is the version number on the last /// ITypeInfo we looked at. If this changes, we know we need to dump the cache. /// private long[] typeInfoVersions; #if DEBUG private string dbgObjName; private string dbgObjClass; #endif private int alwaysValid = 0; ////// /// These are the interfaces we recognize for extended browsing. /// private static Type[] extendedInterfaces = new Type[]{ typeof(NativeMethods.ICategorizeProperties), typeof(NativeMethods.IProvidePropertyBuilder), typeof(NativeMethods.IPerPropertyBrowsing), typeof(NativeMethods.IVsPerPropertyBrowsing), typeof(NativeMethods.IManagedPerPropertyBrowsing)}; ////// /// These are the classes of handlers corresponding to the extended /// interfaces above. /// private static Type[] extendedInterfaceHandlerTypes = new Type[]{ typeof(Com2ICategorizePropertiesHandler), typeof(Com2IProvidePropertyBuilderHandler), typeof(Com2IPerPropertyBrowsingHandler), typeof(Com2IVsPerPropertyBrowsingHandler), typeof(Com2IManagedPerPropertyBrowsingHandler)}; public event EventHandler Disposed; ////// /// Default ctor. /// public Com2Properties(object obj, Com2PropertyDescriptor[] props, int defaultIndex) { #if DEBUG ComNativeDescriptor cnd = new ComNativeDescriptor(); this.dbgObjName = cnd.GetName(obj); if (this.dbgObjName == null) { this.dbgObjName = "(null)"; } this.dbgObjClass = cnd.GetClassName(obj); if (this.dbgObjClass == null) { this.dbgObjClass = "(null)"; } if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Creating Com2Properties for object " + dbgObjName + ", class=" + dbgObjClass); #endif // set up our variables SetProps(props); weakObjRef = new WeakReference(obj); this.defaultIndex = defaultIndex; typeInfoVersions = GetTypeInfoVersions(obj); touchedTime = DateTime.Now.Ticks; } internal bool AlwaysValid { get { return this.alwaysValid > 0; } set { if (value) { if (alwaysValid == 0 && !CheckValid()) { return; } this.alwaysValid++; } else { if (alwaysValid > 0) { this.alwaysValid--; } } } } ////// /// Retrieve the default property. /// public Com2PropertyDescriptor DefaultProperty{ get{ if (!CheckValid(true)) { return null; } if (defaultIndex == -1) { if (props.Length > 0) { return props[0]; } else { return null; } } Debug.Assert(defaultIndex < props.Length, "Whoops! default index is > props.Length"); return props[defaultIndex]; } } ////// /// The object that created the list of properties. This will /// return null if the timeout has passed or the ref has died. /// public object TargetObject{ get{ if (!CheckValid(false) || touchedTime == 0) { #if DEBUG if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("CheckValid called on dead object!"); #endif return null; } return weakObjRef.Target; } } ////// /// How long since these props have been queried. /// public long TicksSinceTouched{ get{ if (touchedTime == 0) { return 0; } return DateTime.Now.Ticks - touchedTime; } } ////// /// Returns the list of properties /// public Com2PropertyDescriptor[] Properties{ get{ CheckValid(true); if (touchedTime == 0 || props == null) { return null; } touchedTime = DateTime.Now.Ticks; // refresh everyone! for (int i = 0; i < props.Length; i++) { props[i].SetNeedsRefresh(Com2PropertyDescriptorRefresh.All, true); } #if DEBUG if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Returning prop array for object " + dbgObjName + ", class=" + dbgObjClass); #endif return props; } } ////// /// Should this guy be refreshed because of old age? /// public bool TooOld{ get{ // check if the property is valid but don't dispose it if it's not CheckValid(false, false); if (touchedTime == 0) { return false; } return TicksSinceTouched > AGE_THRESHHOLD; } } ////// /// Checks the source object for eache extended browsing inteface /// listed in extendedInterfaces and creates a handler from extendedInterfaceHandlerTypes /// to handle it. /// public void AddExtendedBrowsingHandlers(Hashtable handlers) { object target = this.TargetObject; if (target == null) { return; } // process all our registered types Type t; for (int i = 0; i < extendedInterfaces.Length; i++) { t = extendedInterfaces[i]; // is this object an implementor of the interface? // if (t.IsInstanceOfType(target)) { // since handlers must be stateless, check to see if we've already // created one of this type // Com2ExtendedBrowsingHandler handler = (Com2ExtendedBrowsingHandler)handlers[t]; if (handler == null) { handler = (Com2ExtendedBrowsingHandler)Activator.CreateInstance(extendedInterfaceHandlerTypes[i]); handlers[t] = handler; } // make sure we got the right one // if (t.IsAssignableFrom(handler.Interface)) { #if DEBUG if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Adding browsing handler type " + handler.Interface.Name + " to object " + dbgObjName + ", class=" + dbgObjClass); #endif // allow the handler to attach itself to the appropriate properties // handler.SetupPropertyHandlers(props); } else { throw new ArgumentException(SR.GetString(SR.COM2BadHandlerType, t.Name, handler.Interface.Name)); } } } } public void Dispose() { #if DEBUG if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Disposing property manager for " + dbgObjName + ", class=" + dbgObjClass); #endif if (props != null) { if (Disposed != null) { Disposed(this, EventArgs.Empty); } weakObjRef = null; props = null; touchedTime = 0; } } public bool CheckValid() { return CheckValid(false); } ////// /// Make sure this property list is still valid. /// /// 1) WeakRef is still alive /// 2) Our timeout hasn't passed /// public bool CheckValid(bool checkVersions) { return CheckValid(checkVersions, true); } ////// Gets a list of version longs for each type info in the COM object /// representing hte current version stamp, function and variable count. /// If any of these things change, we'll re-fetch the properties. /// private long[] GetTypeInfoVersions(object comObject) { // get type infos // UnsafeNativeMethods.ITypeInfo[] pTypeInfos = Com2TypeInfoProcessor.FindTypeInfos(comObject, false); // build up the info. // long[] versions = new long[pTypeInfos.Length]; for (int i = 0; i < pTypeInfos.Length; i++) { versions [i] = GetTypeInfoVersion(pTypeInfos[i]); } return versions; } private static int countOffset = -1; private static int versionOffset = -1; // we define a struct here so we can use unsafe code to marshal it // as a blob of memory. This is here as a reference to how big and where the members are. // /*private struct tagTYPEATTR { public Guid guid; //16 public int lcid; // 4 public int dwReserved; // 4 public int memidConstructor; // 4 public int memidDestructor; // 4 public IntPtr lpstrSchema; // platform public int cbSizeInstance; // 4 public int typekind; // 4 public short cFuncs; // 2 public short cVars; // 2 public short cImplTypes; // 2 public short cbSizeVft; // 2 public short cbAlignment; // 2 public short wTypeFlags; // 2 public short wMajorVerNum; // 2 public short wMinorVerNum; // 2 public int tdescAlias_unionMember; public short tdescAlias_vt; public int idldescType_dwReserved; public short idldescType_wIDLFlags; }*/ // the offset of the cFunc member in the TYPEATTR structure. // private static int CountMemberOffset { get { if (countOffset == -1) { countOffset = Marshal.SizeOf(typeof(Guid)) + IntPtr.Size + 24; } return countOffset; } } // the offset of the cMajorVerNum member in the TYPEATTR structure. // private static int VersionOffset { get { if (versionOffset == -1) { versionOffset = CountMemberOffset + 12; } return versionOffset; } } private unsafe long GetTypeInfoVersion(UnsafeNativeMethods.ITypeInfo pTypeInfo) { IntPtr pTypeAttr = IntPtr.Zero; int hr = pTypeInfo.GetTypeAttr(ref pTypeAttr); if (!NativeMethods.Succeeded(hr)) { return 0; } System.Runtime.InteropServices.ComTypes.TYPEATTR pTAStruct; try { try { // just access directly...no marshalling needed! // pTAStruct = *(System.Runtime.InteropServices.ComTypes.TYPEATTR*)pTypeAttr; } catch { return 0; } long result = 0; // we pull two things out of the struct: the // number of functions and variables, and the version. // since they are next to each other, we just pull the memory directly. // // the cFuncs and cVars are both shorts, so we read them as one block of ints. // // int* pResult = (int*)&result; byte* pbStruct = (byte*)&pTAStruct; // in the low byte, pull the number of props. // *pResult = *(int*)(pbStruct + CountMemberOffset); // move up to the high word of the long. // pResult++; // now pull out the version info. // *pResult = *(int*)(pbStruct + VersionOffset); // return that composite long. // return result; } finally { pTypeInfo.ReleaseTypeAttr(pTypeAttr); } } internal bool CheckValid(bool checkVersions, bool callDispose) { if (this.AlwaysValid) { return true; } bool valid = weakObjRef != null && weakObjRef.IsAlive; // check the version information for each ITypeInfo the object exposes. // if (valid && checkVersions) { // long[] newTypeInfoVersions = GetTypeInfoVersions(weakObjRef.Target); if (newTypeInfoVersions.Length != typeInfoVersions.Length) { valid = false; } else { // compare each version number to the old one. // for (int i = 0; i < newTypeInfoVersions.Length; i++) { if (newTypeInfoVersions[i] != typeInfoVersions[i]) { valid = false; break; } } } if (!valid) { // update to the new version list we have. // typeInfoVersions = newTypeInfoVersions; } } if (!valid && callDispose) { // weak ref has died, so remove this from the hash table // #if DEBUG if (DbgCom2PropertiesSwitch.TraceVerbose) Debug.WriteLine("Disposing reference to object " + dbgObjName + ", class=" + dbgObjClass + " (weakRef " + (weakObjRef == null ? "null" : "dead") + ")"); #endif Dispose(); } return valid; } ////// /// Set the props for this object, and notify each property /// that we are now it's manager /// internal void SetProps(Com2PropertyDescriptor[] props) { this.props = props; if (props != null) { for (int i = 0; i < props.Length; i++) { props[i].PropertyManager = this; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- VirtualPath.cs
- LocationReferenceValue.cs
- TransactionOptions.cs
- FragmentQueryKB.cs
- LambdaCompiler.cs
- SystemMulticastIPAddressInformation.cs
- XmlIlGenerator.cs
- TypeValidationEventArgs.cs
- SyncOperationState.cs
- PlatformNotSupportedException.cs
- KoreanLunisolarCalendar.cs
- IsolatedStorageException.cs
- DynamicArgumentDialog.cs
- ThreadStateException.cs
- CompiledRegexRunner.cs
- RoutedEventConverter.cs
- StickyNoteAnnotations.cs
- MultiView.cs
- AppDomainProtocolHandler.cs
- DbMetaDataFactory.cs
- RequestStatusBarUpdateEventArgs.cs
- ScrollEventArgs.cs
- shaperfactory.cs
- SystemResources.cs
- Constants.cs
- FormClosingEvent.cs
- DataGridViewLinkColumn.cs
- ListItemParagraph.cs
- SynchronizedInputAdaptor.cs
- ApplicationProxyInternal.cs
- ProcessHostMapPath.cs
- Matrix3D.cs
- BinaryObjectReader.cs
- AuthenticateEventArgs.cs
- Ppl.cs
- PointAnimationUsingPath.cs
- OdbcEnvironment.cs
- TokenizerHelper.cs
- DomNameTable.cs
- SnapLine.cs
- ClientTargetSection.cs
- CompositeCollectionView.cs
- XmlSerializerFactory.cs
- StaticContext.cs
- ControlValuePropertyAttribute.cs
- Screen.cs
- ipaddressinformationcollection.cs
- XPathNodeList.cs
- WebConvert.cs
- ImageSourceValueSerializer.cs
- ApplicationSecurityManager.cs
- SqlConnectionString.cs
- StateChangeEvent.cs
- SystemIcons.cs
- StreamGeometry.cs
- HtmlHead.cs
- FileStream.cs
- SqlExpander.cs
- EditorBrowsableAttribute.cs
- AssemblyFilter.cs
- SplineKeyFrames.cs
- DataObjectFieldAttribute.cs
- MenuTracker.cs
- PermissionSetTriple.cs
- HtmlPageAdapter.cs
- PermissionToken.cs
- CatalogZone.cs
- Single.cs
- Point4DValueSerializer.cs
- ChineseLunisolarCalendar.cs
- DataGridViewHitTestInfo.cs
- KeyMatchBuilder.cs
- ChooseAction.cs
- SecurityListenerSettingsLifetimeManager.cs
- DataTransferEventArgs.cs
- DbBuffer.cs
- Wildcard.cs
- SecurityElement.cs
- hwndwrapper.cs
- WeakReferenceList.cs
- CreateParams.cs
- ObjectDataSourceSelectingEventArgs.cs
- XmlSerializerFormatAttribute.cs
- Panel.cs
- CategoryGridEntry.cs
- TextComposition.cs
- RelationshipEnd.cs
- BufferedStream.cs
- SortDescriptionCollection.cs
- EntityReference.cs
- DataGridTextBox.cs
- CodePageEncoding.cs
- ToolStripSystemRenderer.cs
- DeferrableContentConverter.cs
- TextServicesDisplayAttribute.cs
- ClientEventManager.cs
- GeometryValueSerializer.cs
- LinqExpressionNormalizer.cs
- CodeThrowExceptionStatement.cs
- Cursors.cs