/Microsoft.Scripting/ComInterop/ComTypeLibDesc.cs
C# | 225 lines | 145 code | 42 blank | 38 comment | 20 complexity | 58d1aa78e4367165129733e1292bb68d MD5 | raw file
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Microsoft Public License. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Microsoft Public License, please send an email to
- * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Microsoft Public License.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
-
- #if !SILVERLIGHT // ComObject
-
- #if CODEPLEX_40
- using System;
- #else
- using System; using Microsoft;
- #endif
- using System.Collections.Generic;
- #if CODEPLEX_40
- using System.Linq.Expressions;
- #else
- using Microsoft.Linq.Expressions;
- #endif
- using System.Runtime.InteropServices;
- #if CODEPLEX_40
- using System.Dynamic;
- #else
- using Microsoft.Scripting;
- #endif
- using System.Globalization;
- using ComTypes = System.Runtime.InteropServices.ComTypes;
-
- namespace Microsoft.Scripting.ComInterop {
-
- public sealed class ComTypeLibDesc : IDynamicMetaObjectProvider {
-
- // typically typelibs contain very small number of coclasses
- // so we will just use the linked list as it performs better
- // on small number of entities
- LinkedList<ComTypeClassDesc> _classes;
- Dictionary<string, ComTypeEnumDesc> _enums;
- string _typeLibName;
- ComTypes.TYPELIBATTR _typeLibAttributes;
-
- private static Dictionary<Guid, ComTypeLibDesc> _CachedTypeLibDesc = new Dictionary<Guid, ComTypeLibDesc>();
-
- private ComTypeLibDesc() {
- _enums = new Dictionary<string, ComTypeEnumDesc>();
- _classes = new LinkedList<ComTypeClassDesc>();
- }
-
- public override string ToString() {
- return String.Format(CultureInfo.CurrentCulture, "<type library {0}>", _typeLibName);
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
- public string Documentation {
- get { return String.Empty; }
- }
-
- #region IDynamicMetaObjectProvider Members
-
- DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) {
- return new TypeLibMetaObject(parameter, this);
- }
-
- #endregion
-
- /// <summary>
- /// Reads the latest registered type library for the corresponding GUID,
- /// reads definitions of CoClass'es and Enum's from this library
- /// and creates a IDynamicMetaObjectProvider that allows to instantiate coclasses
- /// and get actual values for the enums.
- /// </summary>
- /// <param name="typeLibGuid">Type Library Guid</param>
- /// <returns>ComTypeLibDesc object</returns>
- [System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.Machine)]
- [System.Runtime.Versioning.ResourceConsumption(System.Runtime.Versioning.ResourceScope.Machine, System.Runtime.Versioning.ResourceScope.Machine)]
- public static ComTypeLibInfo CreateFromGuid(Guid typeLibGuid) {
- // passing majorVersion = -1, minorVersion = -1 will always
- // load the latest typelib
- ComTypes.ITypeLib typeLib = UnsafeNativeMethods.LoadRegTypeLib(ref typeLibGuid, -1, -1, 0);
-
- return new ComTypeLibInfo(GetFromTypeLib(typeLib));
- }
-
- /// <summary>
- /// Gets an ITypeLib object from OLE Automation compatible RCW ,
- /// reads definitions of CoClass'es and Enum's from this library
- /// and creates a IDynamicMetaObjectProvider that allows to instantiate coclasses
- /// and get actual values for the enums.
- /// </summary>
- /// <param name="rcw">OLE automation compatible RCW</param>
- /// <returns>ComTypeLibDesc object</returns>
- public static ComTypeLibInfo CreateFromObject(object rcw) {
- if (Marshal.IsComObject(rcw) == false) {
- throw new ArgumentException("COM object is expected.");
- }
-
- ComTypes.ITypeInfo typeInfo = ComRuntimeHelpers.GetITypeInfoFromIDispatch(rcw as IDispatch, true);
-
- ComTypes.ITypeLib typeLib;
- int typeInfoIndex;
- typeInfo.GetContainingTypeLib(out typeLib, out typeInfoIndex);
-
- return new ComTypeLibInfo(GetFromTypeLib(typeLib));
- }
-
- internal static ComTypeLibDesc GetFromTypeLib(ComTypes.ITypeLib typeLib) {
- // check whether we have already loaded this type library
- ComTypes.TYPELIBATTR typeLibAttr = ComRuntimeHelpers.GetTypeAttrForTypeLib(typeLib);
- ComTypeLibDesc typeLibDesc;
- lock (_CachedTypeLibDesc) {
- if (_CachedTypeLibDesc.TryGetValue(typeLibAttr.guid, out typeLibDesc)) {
- return typeLibDesc;
- }
- }
-
- typeLibDesc = new ComTypeLibDesc();
-
- typeLibDesc._typeLibName = ComRuntimeHelpers.GetNameOfLib(typeLib);
- typeLibDesc._typeLibAttributes = typeLibAttr;
-
- int countTypes = typeLib.GetTypeInfoCount();
- for (int i = 0; i < countTypes; i++) {
- ComTypes.TYPEKIND typeKind;
- typeLib.GetTypeInfoType(i, out typeKind);
-
- ComTypes.ITypeInfo typeInfo;
- if (typeKind == ComTypes.TYPEKIND.TKIND_COCLASS) {
- typeLib.GetTypeInfo(i, out typeInfo);
- ComTypeClassDesc classDesc = new ComTypeClassDesc(typeInfo, typeLibDesc);
- typeLibDesc._classes.AddLast(classDesc);
- } else if (typeKind == ComTypes.TYPEKIND.TKIND_ENUM) {
- typeLib.GetTypeInfo(i, out typeInfo);
- ComTypeEnumDesc enumDesc = new ComTypeEnumDesc(typeInfo, typeLibDesc);
- typeLibDesc._enums.Add(enumDesc.TypeName, enumDesc);
- }
- }
-
- // cached the typelib using the guid as the dictionary key
- lock (_CachedTypeLibDesc) {
- _CachedTypeLibDesc.Add(typeLibAttr.guid, typeLibDesc);
- }
-
- return typeLibDesc;
- }
-
- public object GetTypeLibObjectDesc(string member) {
- foreach (ComTypeClassDesc coclass in _classes) {
- if (member == coclass.TypeName) {
- return coclass;
- }
- }
-
- ComTypeEnumDesc enumDesc;
- if (_enums != null && _enums.TryGetValue(member, out enumDesc) == true)
- return enumDesc;
-
- return null;
- }
-
- // TODO: internal
- public string[] GetMemberNames() {
- string[] retval = new string[_enums.Count + _classes.Count];
- int i = 0;
-
- foreach (ComTypeClassDesc coclass in _classes) {
- retval[i++] = coclass.TypeName;
- }
-
- foreach (KeyValuePair<string, ComTypeEnumDesc> enumDesc in _enums) {
- retval[i++] = enumDesc.Key;
- }
-
- return retval;
- }
-
- internal bool HasMember(string member) {
- foreach (ComTypeClassDesc coclass in _classes) {
- if (member == coclass.TypeName) {
- return true;
- }
- }
-
- if (_enums.ContainsKey(member) == true)
- return true;
-
- return false;
- }
-
- public Guid Guid {
- get { return _typeLibAttributes.guid; }
- }
-
- public short VersionMajor {
- get { return _typeLibAttributes.wMajorVerNum; }
- }
-
- public short VersionMinor {
- get { return _typeLibAttributes.wMinorVerNum; }
- }
-
- public string Name {
- get { return _typeLibName; }
- }
-
- internal ComTypeClassDesc GetCoClassForInterface(string itfName) {
- foreach (ComTypeClassDesc coclass in _classes) {
- if (coclass.Implements(itfName, false)) {
- return coclass;
- }
- }
-
- return null;
- }
- }
- }
-
- #endif