The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ VsaNamedItemScope

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using Microsoft.JScript.Vsa;
  19.     using System;
  20.     using System.Collections;
  21.     using System.Reflection;
  22.     using System.Diagnostics;
  23.    
  24.     //********************************************************************************************
  25.     // VsaNamedItemScope
  26.     //
  27.     // This class is a ScriptObject that acts like a peer for a named item introduced by a host
  28.     // with the exposeMembers flag set.
  29.     // An instance of this object is pushed into the prototype chain of the specified scope
  30.     // so it can participate in name resolution.
  31.     // When asked for a name (field, property or method) an instance of this class forwards
  32.     // the host object the request.
  33.     // The engine should never deal with this class as if it was a "concrete" script object, that
  34.     // is, should never attempt to add a name to this class. This class should be used by the
  35.     // engine only for name resolution.
  36.     //********************************************************************************************
  37.     internal sealed class VsaNamedItemScope : ScriptObject, IActivationObject
  38.     {
  39.        
  40.         internal object namedItem;
  41.         //Used by GetMembers to cache members that must be delegated to other objects
  42.         private SimpleHashtable namedItemWrappedMemberCache;
  43.        
  44.         private IReflect reflectObj;
  45.         private bool recursive;
  46.        
  47.         internal VsaNamedItemScope(object hostObject, ScriptObject parent, VsaEngine engine) : base(parent)
  48.         {
  49.             this.namedItem = hostObject;
  50.             if ((this.reflectObj = hostObject as IReflect) == null)
  51.                 this.reflectObj = Globals.TypeRefs.ToReferenceContext(hostObject.GetType());
  52.             this.recursive = false;
  53.             this.engine = engine;
  54.         }
  55.        
  56.         private static MemberInfo[] GetAndWrapMember(IReflect reflect, object namedItem, string name, BindingFlags bindingAttr)
  57.         {
  58.             PropertyInfo property = reflect.GetProperty(name, bindingAttr);
  59.             if (property != null) {
  60.                 MethodInfo getMethod = JSProperty.GetGetMethod(property, false);
  61.                 MethodInfo setMethod = JSProperty.GetSetMethod(property, false);
  62.                 if ((getMethod != null && !getMethod.IsStatic) || (setMethod != null && !setMethod.IsStatic)) {
  63.                     MethodInfo method = reflect.GetMethod(name, bindingAttr);
  64.                     if (method != null && !method.IsStatic) {
  65.                         MemberInfo[] propMethods = new MemberInfo[1];
  66.                         propMethods[0] = new JSWrappedPropertyAndMethod(property, method, namedItem);
  67.                         return propMethods;
  68.                     }
  69.                 }
  70.             }
  71.             MemberInfo[] members = reflect.GetMember(name, bindingAttr);
  72.             if (members != null && members.Length > 0)
  73.                 return ScriptObject.WrapMembers(members, namedItem);
  74.             return null;
  75.         }
  76.        
  77.         public object GetDefaultThisObject()
  78.         {
  79.             return ((IActivationObject)this.GetParent()).GetDefaultThisObject();
  80.         }
  81.        
  82.         public FieldInfo GetField(string name, int lexLevel)
  83.         {
  84.             throw new JScriptException(JSError.InternalError);
  85.         }
  86.        
  87.         public GlobalScope GetGlobalScope()
  88.         {
  89.             return ((IActivationObject)this.GetParent()).GetGlobalScope();
  90.         }
  91.        
  92.         FieldInfo IActivationObject.GetLocalField(string name)
  93.         {
  94.             Debug.Assert(false);
  95.             return null;
  96.         }
  97.        
  98.         #if !DEBUG
  99.         [DebuggerStepThroughAttribute()]
  100.         [DebuggerHiddenAttribute()]
  101.         #endif
  102.         public object GetMemberValue(string name, int lexlevel)
  103.         {
  104.             if (lexlevel <= 0)
  105.                 return Missing.Value;
  106.             object result = LateBinding.GetMemberValue(this.namedItem, name);
  107.             if (!(result is Missing))
  108.                 return result;
  109.             return ((IActivationObject)parent).GetMemberValue(name, lexlevel - 1);
  110.         }
  111.        
  112.         public override MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
  113.         {
  114.             MemberInfo[] members = null;
  115.             if (!this.recursive && this.reflectObj != null) {
  116.                 this.recursive = true;
  117.                 try {
  118.                     ISite2 site;
  119.                     if (!this.reflectObj.GetType().IsCOMObject || (site = this.engine.Site as ISite2) == null)
  120.                         members = ScriptObject.WrapMembers(this.reflectObj.GetMember(name, bindingAttr), this.namedItem);
  121.                     else if ((members = VsaNamedItemScope.GetAndWrapMember(this.reflectObj, this.namedItem, name, bindingAttr)) == null) {
  122.                         object[] parentChain = site.GetParentChain(this.reflectObj);
  123.                         if (parentChain != null) {
  124.                             int parentChainLength = parentChain.Length;
  125.                             for (int i = 0; i < parentChainLength; i++) {
  126.                                 IReflect parent = parentChain[i] as IReflect;
  127.                                 if (parent != null && (members = VsaNamedItemScope.GetAndWrapMember(parent, parent, name, bindingAttr)) != null)
  128.                                     break;
  129.                             }
  130.                         }
  131.                     }
  132.                 }
  133.                 finally {
  134.                     this.recursive = false;
  135.                 }
  136.             }
  137.             return members == null ? new MemberInfo[0] : members;
  138.         }
  139.        
  140.         public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
  141.         {
  142.             MemberInfo[] members = null;
  143.             if (!this.recursive) {
  144.                 this.recursive = true;
  145.                 try {
  146.                     members = this.reflectObj.GetMembers(bindingAttr);
  147.                     if (members != null)
  148.                         if (members.Length > 0) {
  149.                             SimpleHashtable cache = this.namedItemWrappedMemberCache;
  150.                             if (cache == null)
  151.                                 cache = this.namedItemWrappedMemberCache = new SimpleHashtable(16);
  152.                             members = ScriptObject.WrapMembers(members, this.namedItem, cache);
  153.                         }
  154.                         else
  155.                             members = null;
  156.                 }
  157.                 finally {
  158.                     this.recursive = false;
  159.                 }
  160.             }
  161.             return members;
  162.         }
  163.        
  164.         #if !DEBUG
  165.         [DebuggerStepThroughAttribute()]
  166.         [DebuggerHiddenAttribute()]
  167.         #endif
  168.         internal override object GetMemberValue(string name)
  169.         {
  170.             object retValue = Missing.Value;
  171.            
  172.             if (!this.recursive) {
  173.                 this.recursive = true;
  174.                 try {
  175.                     FieldInfo field = this.reflectObj.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public);
  176.                     if (field == null) {
  177.                         PropertyInfo prop = this.reflectObj.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public);
  178.                         if (prop != null)
  179.                             retValue = JSProperty.GetValue(prop, this.namedItem, null);
  180.                     }
  181.                     else
  182.                         retValue = field.GetValue(this.namedItem);
  183.                    
  184.                     if (retValue is Missing && null != parent)
  185.                         retValue = parent.GetMemberValue(name);
  186.                 }
  187.                 finally {
  188.                     this.recursive = false;
  189.                 }
  190.             }
  191.             return retValue;
  192.         }
  193.        
  194.         #if !DEBUG
  195.         [DebuggerStepThroughAttribute()]
  196.         [DebuggerHiddenAttribute()]
  197.         #endif
  198.         internal override void SetMemberValue(string name, object value)
  199.         {
  200.             bool assigned = false;
  201.             if (!this.recursive) {
  202.                 this.recursive = true;
  203.                 try {
  204.                     FieldInfo field = this.reflectObj.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public);
  205.                     if (field == null) {
  206.                         PropertyInfo prop = this.reflectObj.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.Public);
  207.                         if (prop != null) {
  208.                             JSProperty.SetValue(prop, this.namedItem, value, null);
  209.                             assigned = true;
  210.                         }
  211.                     }
  212.                     else {
  213.                         field.SetValue(this.namedItem, value);
  214.                         assigned = true;
  215.                     }
  216.                    
  217.                     if (!assigned && null != parent)
  218.                         parent.SetMemberValue(name, value);
  219.                 }
  220.                 finally {
  221.                     this.recursive = false;
  222.                 }
  223.             }
  224.         }
  225.     }
  226. }

Developer Fusion