ComNativeDescriptor.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / ComponentModel / COM2Interop / ComNativeDescriptor.cs / 1305376 / ComNativeDescriptor.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

 
namespace System.Windows.Forms.ComponentModel.Com2Interop { 
    using System.Runtime.Serialization.Formatters;
    using System.Runtime.Remoting; 
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.ComponentModel.Design;
    using Microsoft.Win32; 

    /// 
    /// 
    ///     Top level mapping layer between COM Object and TypeDescriptor. 
    ///
    ///  
    internal class ComNativeDescriptor : TypeDescriptionProvider { 

        private static ComNativeDescriptor handler = null; 

        private AttributeCollection staticAttrs = new AttributeCollection(new Attribute[]{BrowsableAttribute.Yes, DesignTimeVisibleAttribute.No});

        ///  
        /// 
        /// Our collection of Object managers (Com2Properties) for native properties 
        ///  
        private WeakHashtable  nativeProps = new WeakHashtable();
 
        /// 
        /// 
        /// Our collection of browsing handlers, which are stateless and shared across objects.
        ///  
        private Hashtable         extendedBrowsingHandlers = new Hashtable();
 
        ///  
        /// 
        /// We increment this every time we look at an Object, at specified 
        /// intervals, we run through the properies list to see if we should
        /// delete any.
        /// 
        private int               clearCount  = 0; 
        private const  int        CLEAR_INTERVAL = 25;
 
        internal static ComNativeDescriptor Instance { 
            get {
                if (handler == null) { 
                    handler = new ComNativeDescriptor();
                }
                return handler;
            } 
        }
 
 
        [
            System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode") 
        ]
        // called via reflection for AutomationExtender stuff. Don't delete!
        //
        public static object GetNativePropertyValue(object component, string propertyName, ref bool succeeded) 
        {
            return Instance.GetPropertyValue(component, propertyName, ref succeeded); 
        } 

 
        /// 
        ///     This method returns a custom type descriptor for the given type / object.
        ///     The objectType parameter is always valid, but the instance parameter may
        ///     be null if no instance was passed to TypeDescriptor.  The method should 
        ///     return a custom type descriptor for the object.  If the method is not
        ///     interested in providing type information for the object it should 
        ///     return null. 
        ///
        ///     This method is prototyped as virtual, and by default returns null 
        ///     if no parent provider was passed.  If a parent provider was passed,
        ///     this method will invoke the parent provider's GetTypeDescriptor
        ///     method.
        ///  
        public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
        { 
            return new ComTypeDescriptor(this, instance); 
        }
 
        internal string GetClassName(Object component) {

            string name = null;
 
            // does IVsPerPropretyBrowsing supply us a name?
            if (component is NativeMethods.IVsPerPropertyBrowsing) { 
               int hr = ((NativeMethods.IVsPerPropertyBrowsing)component).GetClassName(ref name); 
               if (NativeMethods.Succeeded(hr) && name != null) {
                  return name; 
               }
               // otherwise fall through...
            }
 
            UnsafeNativeMethods.ITypeInfo  pTypeInfo = Com2TypeInfoProcessor.FindTypeInfo(component, true);
 
            if (pTypeInfo == null) { 
                //Debug.Fail("The current component failed to return an ITypeInfo");
                return ""; 
            }

            if (pTypeInfo != null) {
                string desc = null; 
                try {
                    pTypeInfo.GetDocumentation(NativeMethods.MEMBERID_NIL, ref name, ref desc, null, null); 
 
                    // strip the leading underscores
                    while (name != null && name.Length > 0 && name[0] == '_') { 
                        name = name.Substring(1);
                    }
                    return name;
                } 
                catch {
                } 
            } 
            return "";
        } 

        internal TypeConverter GetConverter(Object component) {
            return TypeDescriptor.GetConverter(typeof(IComponent));
        } 

        internal Object GetEditor(Object component, Type baseEditorType) { 
            return TypeDescriptor.GetEditor(component.GetType(), baseEditorType); 
        }
 
        internal string GetName(Object component) {

            if (!(component is UnsafeNativeMethods.IDispatch)) {
                return ""; 
            }
 
            int dispid = Com2TypeInfoProcessor.GetNameDispId((UnsafeNativeMethods.IDispatch)component); 
            if (dispid != NativeMethods.MEMBERID_NIL) {
                bool success = false; 
                object value = GetPropertyValue(component, dispid, ref success);

                if (success && value != null) {
                    return value.ToString(); 
                }
            } 
            return ""; 
        }
 
        internal Object GetPropertyValue(Object component, string propertyName, ref bool succeeded) {

            if (!(component is UnsafeNativeMethods.IDispatch)) {
                return null; 
            }
 
            UnsafeNativeMethods.IDispatch iDispatch = (UnsafeNativeMethods.IDispatch)component; 
            string[] names = new string[]{propertyName};
            int[] dispid = new int[1]; 
            dispid[0] = NativeMethods.DISPID_UNKNOWN;
            Guid g = Guid.Empty;
            try {
               int hr = iDispatch.GetIDsOfNames(ref g, names, 1, SafeNativeMethods.GetThreadLCID(), dispid); 

               if (dispid[0] == NativeMethods.DISPID_UNKNOWN || NativeMethods.Failed(hr)) { 
                   return null; 
               }
            } 
            catch {
                return null;
            }
            return GetPropertyValue(component, dispid[0], ref succeeded); 
        }
 
        internal Object GetPropertyValue(Object component, int dispid, ref bool succeeded) { 
            if (!(component is UnsafeNativeMethods.IDispatch)) {
                return null; 
            }
            Object[] pVarResult = new Object[1];
            if (GetPropertyValue(component, dispid, pVarResult) == NativeMethods.S_OK) {
                succeeded = true; 
                return pVarResult[0];
            } 
            else { 
                succeeded = false;
                return null; 
            }
        }

        internal int GetPropertyValue(Object component, int dispid, Object[] retval) { 
            if (!(component is UnsafeNativeMethods.IDispatch)) {
                return NativeMethods.E_NOINTERFACE; 
            } 
            UnsafeNativeMethods.IDispatch iDispatch = (UnsafeNativeMethods.IDispatch)component;
            try { 
                Guid g = Guid.Empty;
                NativeMethods.tagEXCEPINFO pExcepInfo = new NativeMethods.tagEXCEPINFO();
                int hr;
 
                try{
 
                   hr = iDispatch.Invoke(dispid, 
                                             ref g,
                                             SafeNativeMethods.GetThreadLCID(), 
                                             NativeMethods.DISPATCH_PROPERTYGET,
                                             new NativeMethods.tagDISPPARAMS(),
                                             retval,
                                             pExcepInfo, null); 

                   /*if (hr != NativeMethods.S_OK){ 
                     Com2PropertyDescriptor.PrintExceptionInfo(pExcepInfo); 

                   } */ 
                   if (hr == NativeMethods.DISP_E_EXCEPTION) {
                       hr = pExcepInfo.scode;
                   }
 
                }
                catch (ExternalException ex){ 
                    hr = ex.ErrorCode; 
                }
                return hr; 
            }
            catch {
                //Debug.Fail(e.ToString() + " " + component.GetType().GUID.ToString() + " " + component.ToString());
            } 
            return NativeMethods.E_FAIL;
        } 
 
        /// 
        ///  
        /// Checks if the given dispid matches the dispid that the Object would like to specify
        /// as its identification proeprty (Name, ID, etc).
        /// 
        internal bool IsNameDispId(Object obj, int dispid) { 
            if (obj == null || !obj.GetType().IsCOMObject) {
                return false; 
            } 
            return dispid == Com2TypeInfoProcessor.GetNameDispId((UnsafeNativeMethods.IDispatch)obj);
        } 

        /// 
        /// 
        /// Checks all our property manages to see if any have become invalid. 
        /// 
        private void CheckClear(Object component) { 
 
            // walk the list every so many calls
            if ((++clearCount % CLEAR_INTERVAL) == 0) { 

               lock(nativeProps) {
                   clearCount = 0;
 
                   List disposeList = null;
                   Com2Properties entry; 
 
                   // first walk the list looking for items that need to be
                   // cleaned out. 
                   //
                   foreach(DictionaryEntry de in nativeProps) {

                        entry = de.Value as Com2Properties;
 
                        if (entry != null && entry.TooOld) {
                            if (disposeList == null) { 
                                disposeList = new List(3); 
                            }
                            disposeList.Add(de.Key); 
                        }
                   }

                   // now run through the ones that are dead and dispose them. 
                   // there's going to be a very small number of these.
                   // 
                   if (disposeList != null) { 
                       object oldKey;
                       for (int i = disposeList.Count - 1; i >= 0; i--) { 
                          oldKey = disposeList[i];
                          entry = nativeProps[oldKey] as Com2Properties;

                          if (entry != null) { 
                               entry.Disposed -= new EventHandler(OnPropsInfoDisposed);
                               entry.Dispose(); 
                               nativeProps.Remove(oldKey); 
                          }
                       } 
                   }
                }
            }
        } 

        ///  
        ///  
        /// Gets the properties manager for an Object.
        ///  
        private Com2Properties GetPropsInfo(Object component) {
            // check caches if necessary
            //
            CheckClear(component); 

            // Get the property info Object 
            // 
            Com2Properties propsInfo = (Com2Properties)nativeProps[component];
 
            // if we dont' have one, create one and set it up
            //
            if (propsInfo == null || !propsInfo.CheckValid()) {
                propsInfo = Com2TypeInfoProcessor.GetProperties(component); 
                if (propsInfo != null) {
                    propsInfo.Disposed += new EventHandler(OnPropsInfoDisposed); 
                    nativeProps.SetWeak(component, propsInfo); 
                    propsInfo.AddExtendedBrowsingHandlers(extendedBrowsingHandlers);
                } 
            }
            return propsInfo;
        }
 
        /// 
        ///  
        /// Got attributes? 
        /// 
        internal AttributeCollection GetAttributes(Object component) { 

            ArrayList attrs = new ArrayList();

            if (component is NativeMethods.IManagedPerPropertyBrowsing) { 
                Object[] temp = Com2IManagedPerPropertyBrowsingHandler.GetComponentAttributes((NativeMethods.IManagedPerPropertyBrowsing)component, NativeMethods.MEMBERID_NIL);
                for (int i = 0; i < temp.Length; ++i) { 
                    attrs.Add(temp[i]); 
                }
            } 

            if (Com2ComponentEditor.NeedsComponentEditor(component)) {
                EditorAttribute a = new EditorAttribute(typeof(Com2ComponentEditor), typeof(ComponentEditor));
                attrs.Add(a); 
            }
 
            if (attrs == null || attrs.Count == 0) { 
                return staticAttrs;
            } 
            else {
                Attribute[] temp = new Attribute[attrs.Count];
                attrs.CopyTo(temp, 0);
                return new AttributeCollection(temp); 
            }
        } 
 
        /// 
        ///  
        /// Default Property, please
        /// 
        internal PropertyDescriptor GetDefaultProperty(Object component) {
            CheckClear(component); 

            Com2Properties propsInfo = GetPropsInfo(component); 
            if (propsInfo != null) { 
                return propsInfo.DefaultProperty;
            } 
            return null;
        }

        internal EventDescriptorCollection GetEvents(Object component) { 
            return new EventDescriptorCollection(null);
        } 
 
        internal EventDescriptorCollection GetEvents(Object component, Attribute[] attributes) {
            return new EventDescriptorCollection(null); 
        }

        internal EventDescriptor GetDefaultEvent(Object component) {
            return null; 
        }
 
        ///  
        /// Props!
        ///  
        [SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
        internal PropertyDescriptorCollection GetProperties(Object component, Attribute[] attributes) {

            Com2Properties propsInfo = GetPropsInfo(component); 

            if (propsInfo == null) { 
                return PropertyDescriptorCollection.Empty; 
            }
 
            try {
                propsInfo.AlwaysValid = true;
                PropertyDescriptor[] props = propsInfo.Properties;
 
                //Debug.Assert(propDescList.Count > 0, "Didn't add any properties! (propInfos=0)");
                return new PropertyDescriptorCollection(props); 
            } 
            finally {
                propsInfo.AlwaysValid = false; 
            }
        }

        ///  
        /// Fired when the property info gets disposed.
        ///  
        private void OnPropsInfoDisposed(object sender, EventArgs e) {
 
            Com2Properties propsInfo = sender as Com2Properties;
 
            if (propsInfo != null) {
                propsInfo.Disposed -= new EventHandler(OnPropsInfoDisposed);

                lock(nativeProps) { 

                    // find the key 
                    object key = propsInfo.TargetObject; 

                    if (key == null && nativeProps.ContainsValue(propsInfo)) {
 
                        // need to find it - the target object has probably been cleaned out
                        // of the Com2Properties object already, so we run through the
                        // hashtable looking for the value, so we know what key to remove.
                        // 
                        foreach (DictionaryEntry de in nativeProps) {

                            if (de.Value == propsInfo) { 
                                key = de.Key; 
                                break;
                            } 
                        }

                        if (key == null)  {
                            Debug.Fail("Failed to find Com2 properties key on dispose."); 
                            return;
                        } 
                    } 

                    nativeProps.Remove(key); 
               }
            }
        }
 
        /// 
        ///  
        /// Looks at at value's type and creates an editor based on that.  We use this to decide which editor to use 
        /// for a generic variant.
        ///  
        internal static void ResolveVariantTypeConverterAndTypeEditor(Object propertyValue, ref TypeConverter currentConverter, Type editorType, ref Object currentEditor) {

            Object curValue = propertyValue;
            if (curValue != null && curValue != null && !Convert.IsDBNull(curValue)){ 
                  Type t = curValue.GetType();
                  TypeConverter subConverter = TypeDescriptor.GetConverter(t); 
                  if (subConverter != null && subConverter.GetType() != typeof(TypeConverter)){ 
                     currentConverter = subConverter;
                  } 
                  Object subEditor = TypeDescriptor.GetEditor(t, editorType);
                  if (subEditor != null) {
                     currentEditor = subEditor;
                  } 
            }
        } 
 
        /// 
        ///     This type descriptor sits on top of a ComNativeDescriptor 
        /// 
        private sealed class ComTypeDescriptor : ICustomTypeDescriptor
        {
            private ComNativeDescriptor         _handler; 
            private object                      _instance;
 
            ///  
            ///     Creates a new WalkingTypeDescriptor.
            ///  
            internal ComTypeDescriptor(ComNativeDescriptor handler, object instance)
            {
                _handler = handler;
                _instance = instance; 
            }
 
            ///  
            ///     ICustomTypeDescriptor implementation.
            ///  
            AttributeCollection ICustomTypeDescriptor.GetAttributes()
            {
                return _handler.GetAttributes(_instance);
            } 

            ///  
            ///     ICustomTypeDescriptor implementation. 
            /// 
            string ICustomTypeDescriptor.GetClassName() 
            {
                return _handler.GetClassName(_instance);
            }
 
            /// 
            ///     ICustomTypeDescriptor implementation. 
            ///  
            string ICustomTypeDescriptor.GetComponentName()
            { 
                return _handler.GetName(_instance);
            }

            ///  
            ///     ICustomTypeDescriptor implementation.
            ///  
            TypeConverter ICustomTypeDescriptor.GetConverter() 
            {
                return _handler.GetConverter(_instance); 
            }

            /// 
            ///     ICustomTypeDescriptor implementation. 
            /// 
            EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() 
            { 
                return _handler.GetDefaultEvent(_instance);
            } 

            /// 
            ///     ICustomTypeDescriptor implementation.
            ///  
            PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
            { 
                return _handler.GetDefaultProperty(_instance); 
            }
 
            /// 
            ///     ICustomTypeDescriptor implementation.
            /// 
            object ICustomTypeDescriptor.GetEditor(Type editorBaseType) 
            {
                return _handler.GetEditor(_instance, editorBaseType); 
            } 

            ///  
            ///     ICustomTypeDescriptor implementation.
            /// 
            EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
            { 
                return _handler.GetEvents(_instance);
            } 
 
            /// 
            ///     ICustomTypeDescriptor implementation. 
            /// 
            EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
            {
                return _handler.GetEvents(_instance, attributes); 
            }
 
            ///  
            ///     ICustomTypeDescriptor implementation.
            ///  
            PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
            {
                return _handler.GetProperties(_instance, null);
            } 

            ///  
            ///     ICustomTypeDescriptor implementation. 
            /// 
            PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) 
            {
                return _handler.GetProperties(_instance, attributes);
            }
 
            /// 
            ///     ICustomTypeDescriptor implementation. 
            ///  
            object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
            { 
                return _instance;
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK