When you have a System.Type that is a component, the best way to get its public properties is to use System.ComponentModel.TypeDescriptor.GetProperties(type), rather than System.Type.GetProperties(). This is so because a component type can have a designer which is able to add new properties to the type, and to remove or change existing properties. For example, controls have a Locked property that is added by the designer of controls (ControlDesigner class), it is not a property that belongs to the System.Windows.Forms.Control type.
If the type is not a component, I guess that System.ComponentModel.TypeDescriptor.GetProperties returns the same public properties than System.Type.GetProperties. System.ComponentModel.TypeDescriptor.GetProperties returns a collection of PropertyDescriptor, which has an IsBrowsable property that tells you if a property is browsable or not.
So, the other day I got an strange issue: I was calling System.ComponentModel.TypeDescriptor.GetProperties on the VSLangProj80.ProjectProperties3 type (which is not a component type but my code was called other times with types that are components), to get the properties that are likely to exist in the EnvDTE.Project.Properties collection. And I got in the results the “AbsoluteProjectDirectory” property, that I noticed that didn’t appear in the Object Browser of Visual Studio, despite its IsBrowsable property returning True. How come?
I was aware that VSLangProj80 stuff is not pure .NET but an imported typelib or something like that, but it was not until I used .NET Reflector that I discovered that the get accessor method of the AbsoluteProjectDirectory property has the System.Runtime.InteropServices.TypeLibFuncFlags attribute with the &H40 value:
<DispId(&H2732)> _ ReadOnly Property AbsoluteProjectDirectory As <MarshalAs(UnmanagedType.BStr)> String <MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime), DispId(&H2732), TypeLibFunc(CShort(&H40))> _ Get ... End Get End Property
which matches the FHidden value:
<Serializable, Flags, ComVisible(True)> _ Public Enum TypeLibFuncFlags ' Fields FBindable = 4 FDefaultBind = &H20 FDefaultCollelem = &H100 FDisplayBind = &H10 FHidden = &H40 FImmediateBind = &H1000 FNonBrowsable = &H400 FReplaceable = &H800 FRequestEdit = 8 FRestricted = 1 FSource = 2 FUiDefault = &H200 FUsesGetLastError = &H80 End Enum
That explained the issue and I was able to tweak my code to deal with that case. BTW, notice that there is also a TypeLibFuncFlags.FNonBrowsable flag.