1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Microsoft Public License. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Microsoft Public License, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Microsoft Public License.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
15 using System; using Microsoft;
18 #if !SILVERLIGHT // ComObject
20 using System.Collections;
21 using System.Collections.Generic;
22 using System.Runtime.InteropServices.ComTypes;
23 using System.Security;
24 using System.Threading;
25 using ComTypes = System.Runtime.InteropServices.ComTypes;
28 namespace System.Dynamic {
30 namespace Microsoft.Scripting {
33 internal class ComTypeDesc {
34 private string _typeName;
35 private string _documentation;
38 //Hashtable is threadsafe for multiple readers single writer.
39 //Enumerating and writing is mutually exclusive so require locking.
40 private Hashtable _funcs;
41 private Hashtable _puts;
42 private Hashtable _putRefs;
43 private ComMethodDesc _getItem;
44 private ComMethodDesc _setItem;
46 private Dictionary<string, ComEventDesc> _events;
48 private static readonly Dictionary<string, ComEventDesc> _EmptyEventsDict = new Dictionary<string, ComEventDesc>();
50 internal ComTypeDesc(ITypeInfo typeInfo) {
51 if (typeInfo != null) {
52 ComRuntimeHelpers.GetInfoFromType(typeInfo, out _typeName, out _documentation);
57 internal static ComTypeDesc FromITypeInfo(ComTypes.ITypeInfo typeInfo, ComTypes.TYPEATTR typeAttr) {
58 if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_COCLASS) {
59 return new ComTypeClassDesc(typeInfo);
60 } else if (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_ENUM) {
61 return new ComTypeEnumDesc(typeInfo);
62 } else if ((typeAttr.typekind == ComTypes.TYPEKIND.TKIND_DISPATCH) ||
63 (typeAttr.typekind == ComTypes.TYPEKIND.TKIND_INTERFACE)) {
65 return new ComTypeDesc(typeInfo);
67 throw Error.UnsupportedEnumType();
71 internal static ComTypeDesc CreateEmptyTypeDesc() {
72 ComTypeDesc typeDesc = new ComTypeDesc(null);
73 typeDesc._funcs = new Hashtable();
74 typeDesc._puts = new Hashtable();
75 typeDesc._putRefs = new Hashtable();
76 typeDesc._events = _EmptyEventsDict;
81 internal static Dictionary<string, ComEventDesc> EmptyEvents {
82 get { return _EmptyEventsDict; }
85 internal Hashtable Funcs {
86 get { return _funcs; }
87 set { _funcs = value; }
90 internal Hashtable Puts {
91 set { _puts = value; }
94 internal Hashtable PutRefs {
95 set { _putRefs = value; }
98 internal Dictionary<string, ComEventDesc> Events {
99 get { return _events; }
100 set { _events = value; }
103 internal bool TryGetFunc(string name, out ComMethodDesc method) {
104 name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
105 if (_funcs.ContainsKey(name)) {
106 method = _funcs[name] as ComMethodDesc;
113 internal void AddFunc(string name, ComMethodDesc method) {
114 name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
116 _funcs[name] = method;
120 internal bool TryGetPut(string name, out ComMethodDesc method) {
121 name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
122 if (_puts.ContainsKey(name)) {
123 method = _puts[name] as ComMethodDesc;
130 internal void AddPut(string name, ComMethodDesc method) {
131 name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
133 _puts[name] = method;
137 internal bool TryGetPutRef(string name, out ComMethodDesc method) {
138 name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
139 if (_putRefs.ContainsKey(name)) {
140 method = _putRefs[name] as ComMethodDesc;
146 internal void AddPutRef(string name, ComMethodDesc method) {
147 name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
149 _putRefs[name] = method;
153 internal bool TryGetEvent(string name, out ComEventDesc @event) {
154 name = name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
155 return _events.TryGetValue(name, out @event);
158 internal string[] GetMemberNames(bool dataOnly) {
159 var names = new Dictionary<string, object>();
162 foreach (ComMethodDesc func in _funcs.Values) {
163 if (!dataOnly || func.IsDataMember) {
164 names.Add(func.Name, null);
171 foreach (ComMethodDesc func in _puts.Values) {
172 if (!names.ContainsKey(func.Name)) {
173 names.Add(func.Name, null);
179 foreach (ComMethodDesc func in _putRefs.Values) {
180 if (!names.ContainsKey(func.Name)) {
181 names.Add(func.Name, null);
186 if (_events != null && _events.Count > 0) {
187 foreach (string name in _events.Keys) {
188 if (!names.ContainsKey(name)) {
189 names.Add(name, null);
195 string[] result = new string[names.Keys.Count];
196 names.Keys.CopyTo(result, 0);
200 internal string TypeName {
201 get { return _typeName; }
205 get { return _guid; }
206 set { _guid = value; }
209 internal ComMethodDesc GetItem {
210 get { return _getItem; }
213 internal void EnsureGetItem(ComMethodDesc candidate) {
214 Interlocked.CompareExchange(ref _getItem, candidate, null);
217 internal ComMethodDesc SetItem {
218 get { return _setItem; }
221 internal void EnsureSetItem(ComMethodDesc candidate) {
222 Interlocked.CompareExchange(ref _setItem, candidate, null);