PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Microsoft.Scripting/Actions/MethodGroup.cs

https://bitbucket.org/stefanrusek/xronos
C# | 192 lines | 131 code | 28 blank | 33 comment | 22 complexity | 7e2a29529400a61adbf954d719dc7cbb MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  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.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if CODEPLEX_40
  16. using System;
  17. #else
  18. using System; using Microsoft;
  19. #endif
  20. using System.Collections.Generic;
  21. using System.Diagnostics;
  22. #if CODEPLEX_40
  23. using System.Linq.Expressions;
  24. #else
  25. using Microsoft.Linq.Expressions;
  26. #endif
  27. using System.Reflection;
  28. using System.Threading;
  29. using Microsoft.Contracts;
  30. namespace Microsoft.Scripting.Actions {
  31. /// <summary>
  32. /// MethodGroup's represent a unique collection of method's. Typically this
  33. /// unique set is all the methods which are overloaded by the same name including
  34. /// methods with different arity. These methods represent a single logically
  35. /// overloaded element of a .NET type.
  36. ///
  37. /// The base DLR binders will produce MethodGroup's when provided with a MemberGroup
  38. /// which contains only methods. The MethodGroup's will be unique instances per
  39. /// each unique group of methods.
  40. /// </summary>
  41. public class MethodGroup : MemberTracker {
  42. private MethodTracker[] _methods;
  43. private Dictionary<TypeList, MethodGroup> _boundGenerics;
  44. internal MethodGroup(params MethodTracker[] methods) {
  45. _methods = methods;
  46. }
  47. public override TrackerTypes MemberType {
  48. get { return TrackerTypes.MethodGroup; }
  49. }
  50. public override Type DeclaringType {
  51. get { return _methods[0].DeclaringType; }
  52. }
  53. public override string Name {
  54. get { return _methods[0].Name; }
  55. }
  56. public bool ContainsInstance {
  57. get {
  58. foreach (MethodTracker mt in _methods) {
  59. if (!mt.IsStatic) return true;
  60. }
  61. return false;
  62. }
  63. }
  64. public bool ContainsStatic {
  65. get {
  66. foreach (MethodTracker mt in _methods) {
  67. if (mt.IsStatic) return true;
  68. }
  69. return false;
  70. }
  71. }
  72. public IList<MethodTracker> Methods {
  73. get {
  74. return _methods;
  75. }
  76. }
  77. public MethodBase[] GetMethodBases() {
  78. MethodBase[] methods = new MethodBase[Methods.Count];
  79. for (int i = 0; i < Methods.Count; i++) {
  80. methods[i] = Methods[i].Method;
  81. }
  82. return methods;
  83. }
  84. public override Expression GetValue(Expression context, ActionBinder binder, Type type) {
  85. return base.GetValue(context, binder, type);
  86. }
  87. public override MemberTracker BindToInstance(Expression instance) {
  88. if (ContainsInstance) {
  89. return new BoundMemberTracker(this, instance);
  90. }
  91. return this;
  92. }
  93. protected internal override Expression GetBoundValue(Expression context, ActionBinder binder, Type type, Expression instance) {
  94. return binder.ReturnMemberTracker(type, BindToInstance(instance));
  95. }
  96. /// <summary>
  97. /// Returns a BuiltinFunction bound to the provided type arguments. Returns null if the binding
  98. /// cannot be performed.
  99. /// </summary>
  100. public MethodGroup MakeGenericMethod(Type[] types) {
  101. TypeList tl = new TypeList(types);
  102. // check for cached method first...
  103. MethodGroup mg;
  104. if (_boundGenerics != null) {
  105. lock (_boundGenerics) {
  106. if (_boundGenerics.TryGetValue(tl, out mg)) {
  107. return mg;
  108. }
  109. }
  110. }
  111. // Search for generic targets with the correct arity (number of type parameters).
  112. // Compatible targets must be MethodInfos by definition (constructors never take
  113. // type arguments).
  114. List<MethodTracker> targets = new List<MethodTracker>(Methods.Count);
  115. foreach (MethodTracker mt in Methods) {
  116. MethodInfo mi = mt.Method;
  117. if (mi.ContainsGenericParameters && mi.GetGenericArguments().Length == types.Length)
  118. targets.Add((MethodTracker)MemberTracker.FromMemberInfo(mi.MakeGenericMethod(types)));
  119. }
  120. if (targets.Count == 0) {
  121. return null;
  122. }
  123. // Build a new MethodGroup that will contain targets with bound type arguments & cache it.
  124. mg = new MethodGroup(targets.ToArray());
  125. EnsureBoundGenericDict();
  126. lock (_boundGenerics) {
  127. _boundGenerics[tl] = mg;
  128. }
  129. return mg;
  130. }
  131. private void EnsureBoundGenericDict() {
  132. if (_boundGenerics == null) {
  133. Interlocked.CompareExchange<Dictionary<TypeList, MethodGroup>>(
  134. ref _boundGenerics,
  135. new Dictionary<TypeList, MethodGroup>(1),
  136. null);
  137. }
  138. }
  139. private class TypeList {
  140. private Type[] _types;
  141. public TypeList(Type[] types) {
  142. Debug.Assert(types != null);
  143. _types = types;
  144. }
  145. [Confined]
  146. public override bool Equals(object obj) {
  147. TypeList tl = obj as TypeList;
  148. if (tl == null || _types.Length != tl._types.Length) return false;
  149. for (int i = 0; i < _types.Length; i++) {
  150. if (_types[i] != tl._types[i]) return false;
  151. }
  152. return true;
  153. }
  154. [Confined]
  155. public override int GetHashCode() {
  156. int hc = 6551;
  157. foreach (Type t in _types) {
  158. hc = (hc << 5) ^ t.GetHashCode();
  159. }
  160. return hc;
  161. }
  162. }
  163. }
  164. }