PageRenderTime 61ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/DICK.B1/IronPython/Runtime/Types/ReflectedGetterSetter.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 210 lines | 159 code | 31 blank | 20 comment | 39 complexity | 277fb31bb13089f286a7dbf9caba3ebc 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. using System;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using System.Reflection;
  19. using System.Runtime.CompilerServices;
  20. using IronPython.Runtime.Operations;
  21. using Microsoft.Scripting.Generation;
  22. using Microsoft.Scripting.Runtime;
  23. using Microsoft.Scripting.Utils;
  24. namespace IronPython.Runtime.Types {
  25. /// <summary>
  26. /// Base class for properties backed by methods. These include our slot properties,
  27. /// indexers, and normal properties. This class provides the storage of these as well
  28. /// as the storage of our optimized getter/setter methods, documentation for the property,
  29. /// etc...
  30. /// </summary>
  31. public abstract class ReflectedGetterSetter : PythonTypeSlot {
  32. private MethodInfo/*!*/[]/*!*/ _getter, _setter;
  33. private readonly NameType _nameType;
  34. private BuiltinFunction _getfunc, _setfunc;
  35. protected ReflectedGetterSetter(MethodInfo[]/*!*/ getter, MethodInfo[]/*!*/ setter, NameType nt) {
  36. Debug.Assert(getter != null);
  37. Debug.Assert(setter != null);
  38. _getter = RemoveNullEntries(getter);
  39. _setter = RemoveNullEntries(setter);
  40. _nameType = nt;
  41. }
  42. protected ReflectedGetterSetter(ReflectedGetterSetter from) {
  43. _getter = from._getter;
  44. _setter = from._setter;
  45. _nameType = from._nameType;
  46. }
  47. internal void AddGetter(MethodInfo mi) {
  48. lock (this) {
  49. _getter = ArrayUtils.Append(_getter, mi);
  50. MakeGetFunc();
  51. }
  52. }
  53. private void MakeGetFunc() {
  54. _getfunc = PythonTypeOps.GetBuiltinFunction(DeclaringType, __name__, _getter);
  55. }
  56. internal void AddSetter(MethodInfo mi) {
  57. lock (this) {
  58. _setter = ArrayUtils.Append(_setter, mi);
  59. MakeSetFunc();
  60. }
  61. }
  62. private void MakeSetFunc() {
  63. _setfunc = PythonTypeOps.GetBuiltinFunction(DeclaringType, __name__, _setter);
  64. }
  65. internal abstract Type DeclaringType {
  66. get;
  67. }
  68. public abstract string __name__ {
  69. get;
  70. }
  71. public PythonType/*!*/ __objclass__ {
  72. get {
  73. return DynamicHelpers.GetPythonTypeFromType(DeclaringType);
  74. }
  75. }
  76. internal MethodInfo/*!*/[]/*!*/ Getter {
  77. get {
  78. return _getter;
  79. }
  80. }
  81. internal MethodInfo/*!*/[]/*!*/ Setter {
  82. get {
  83. return _setter;
  84. }
  85. }
  86. public virtual PythonType PropertyType {
  87. [PythonHidden]
  88. get {
  89. if (Getter != null && Getter.Length > 0) {
  90. return DynamicHelpers.GetPythonTypeFromType(Getter[0].ReturnType);
  91. }
  92. return DynamicHelpers.GetPythonTypeFromType(typeof(object));
  93. }
  94. }
  95. internal NameType NameType {
  96. get {
  97. return _nameType;
  98. }
  99. }
  100. internal object CallGetter(CodeContext context, SiteLocalStorage<CallSite<Func<CallSite, CodeContext, object, object[], object>>> storage, object instance, object[] args) {
  101. if (NeedToReturnProperty(instance, Getter)) {
  102. return this;
  103. }
  104. if (Getter.Length == 0) {
  105. throw new MissingMemberException("unreadable property");
  106. }
  107. if (_getfunc == null) {
  108. lock (this) {
  109. if (_getfunc == null) {
  110. MakeGetFunc();
  111. }
  112. }
  113. }
  114. return _getfunc.Call(context, storage, instance, args);
  115. }
  116. internal object CallTarget(CodeContext context, SiteLocalStorage<CallSite<Func<CallSite, CodeContext, object, object[], object>>> storage, MethodInfo[] targets, object instance, params object[] args) {
  117. BuiltinFunction target = PythonTypeOps.GetBuiltinFunction(DeclaringType, __name__, targets);
  118. return target.Call(context, storage, instance, args);
  119. }
  120. internal static bool NeedToReturnProperty(object instance, MethodInfo[] mis) {
  121. if (instance == null) {
  122. if (mis.Length == 0) {
  123. return true;
  124. }
  125. foreach (MethodInfo mi in mis) {
  126. if (!mi.IsStatic ||
  127. (mi.IsDefined(typeof(PropertyMethodAttribute), true) &&
  128. !mi.IsDefined(typeof(StaticExtensionMethodAttribute), true)) &&
  129. !mi.IsDefined(typeof(WrapperDescriptorAttribute), true)) {
  130. return true;
  131. }
  132. }
  133. }
  134. return false;
  135. }
  136. internal bool CallSetter(CodeContext context, SiteLocalStorage<CallSite<Func<CallSite, CodeContext, object, object[], object>>> storage, object instance, object[] args, object value) {
  137. if (NeedToReturnProperty(instance, Setter)) {
  138. return false;
  139. }
  140. if (_setfunc == null) {
  141. lock (this) {
  142. if (_setfunc == null) {
  143. MakeSetFunc();
  144. }
  145. }
  146. }
  147. if (args.Length != 0) {
  148. _setfunc.Call(context, storage, instance, ArrayUtils.Append(args, value));
  149. } else {
  150. _setfunc.Call(context, storage, instance, new [] { value });
  151. }
  152. return true;
  153. }
  154. internal override bool IsAlwaysVisible {
  155. get {
  156. return _nameType == NameType.PythonProperty;
  157. }
  158. }
  159. private static MethodInfo[] RemoveNullEntries(MethodInfo[] mis) {
  160. List<MethodInfo> res = null;
  161. for (int i = 0; i < mis.Length; i++) {
  162. if (mis[i] == null) {
  163. if (res == null) {
  164. res = new List<MethodInfo>();
  165. for (int j = 0; j < i; j++) {
  166. res.Add(mis[j]);
  167. }
  168. }
  169. } else if (res != null) {
  170. res.Add(mis[i]);
  171. }
  172. }
  173. if (res != null) {
  174. return res.ToArray();
  175. }
  176. return mis;
  177. }
  178. }
  179. }