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

  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 System;
  19.     using System.Reflection;
  20.     using System.Reflection.Emit;
  21.     using System.Globalization;
  22.     using System.Diagnostics;
  23.    
  24.     internal class JSProperty : PropertyInfo
  25.     {
  26.         private string name;
  27.         private ParameterInfo[] formal_parameters;
  28.         internal PropertyBuilder metaData;
  29.         internal JSMethod getter;
  30.         internal JSMethod setter;
  31.        
  32.         internal JSProperty(string name)
  33.         {
  34.             this.name = name;
  35.             this.formal_parameters = null;
  36.             this.getter = null;
  37.             this.setter = null;
  38.         }
  39.        
  40.         public override PropertyAttributes Attributes {
  41.             get { return PropertyAttributes.None; }
  42.         }
  43.        
  44.         public override bool CanRead {
  45.             get { return JSProperty.GetGetMethod(this, true) != null; }
  46.         }
  47.        
  48.         public override bool CanWrite {
  49.             get { return JSProperty.GetSetMethod(this, true) != null; }
  50.         }
  51.        
  52.         internal virtual string GetClassFullName()
  53.         {
  54.             if (this.getter != null)
  55.                 return this.getter.GetClassFullName();
  56.             else
  57.                 return this.setter.GetClassFullName();
  58.         }
  59.        
  60.         internal bool GetterAndSetterAreConsistent()
  61.         {
  62.             if (this.getter == null || this.setter == null)
  63.                 return true;
  64.             ((JSFieldMethod)this.getter).func.PartiallyEvaluate();
  65.             ((JSFieldMethod)this.setter).func.PartiallyEvaluate();
  66.             ParameterInfo[] getterPars = this.getter.GetParameters();
  67.             ParameterInfo[] setterPars = this.setter.GetParameters();
  68.             int n = getterPars.Length;
  69.             int m = setterPars.Length;
  70.             if (n != m - 1)
  71.                 return false;
  72.             if (!((JSFieldMethod)this.getter).func.ReturnType(null).Equals(((ParameterDeclaration)setterPars[n]).type.ToIReflect()))
  73.                 return false;
  74.             for (int i = 0; i < n; i++)
  75.                 if (((ParameterDeclaration)getterPars[i]).type.ToIReflect() != ((ParameterDeclaration)setterPars[i]).type.ToIReflect())
  76.                     return false;
  77.             return (this.getter.Attributes & ~MethodAttributes.Abstract) == (this.setter.Attributes & ~MethodAttributes.Abstract);
  78.         }
  79.        
  80.         public override Type DeclaringType {
  81.             get {
  82.                 if (this.getter != null)
  83.                     return this.getter.DeclaringType;
  84.                 else
  85.                     return this.setter.DeclaringType;
  86.             }
  87.         }
  88.        
  89.         public override sealed object[] GetCustomAttributes(Type t, bool inherit)
  90.         {
  91.             return new object[0];
  92.         }
  93.        
  94.         public override sealed object[] GetCustomAttributes(bool inherit)
  95.         {
  96.             if (this.getter != null)
  97.                 return this.getter.GetCustomAttributes(true);
  98.             if (this.setter != null)
  99.                 return this.setter.GetCustomAttributes(true);
  100.             return new object[0];
  101.         }
  102.        
  103.         #if !DEBUG
  104.         [DebuggerStepThroughAttribute()]
  105.         [DebuggerHiddenAttribute()]
  106.         #endif
  107.         static internal object GetValue(PropertyInfo prop, object obj, object[] index)
  108.         {
  109.             JSProperty jsprop = prop as JSProperty;
  110.             if (jsprop != null)
  111.                 return jsprop.GetValue(obj, BindingFlags.ExactBinding, null, index, null);
  112.             JSWrappedProperty jswrappedprop = prop as JSWrappedProperty;
  113.             if (jswrappedprop != null)
  114.                 return jswrappedprop.GetValue(obj, BindingFlags.ExactBinding, null, index, null);
  115.             MethodInfo meth = JSProperty.GetGetMethod(prop, false);
  116.             if (meth != null) {
  117.                 try {
  118.                     return meth.Invoke(obj, BindingFlags.ExactBinding, null, index, null);
  119.                 }
  120.                 catch (TargetInvocationException e) {
  121.                     throw e.InnerException;
  122.                 }
  123.             }
  124.             throw new MissingMethodException();
  125.         }
  126.        
  127.         #if !DEBUG
  128.         [DebuggerStepThroughAttribute()]
  129.         [DebuggerHiddenAttribute()]
  130.         #endif
  131.         public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
  132.         {
  133.             MethodInfo getter = this.getter;
  134.             JSObject jsOb = obj as JSObject;
  135.             if (getter == null && jsOb != null) {
  136.                 getter = jsOb.GetMethod("get_" + this.name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  137.                 JSWrappedMethod wrm = getter as JSWrappedMethod;
  138.                 if (wrm != null)
  139.                     getter = wrm.method;
  140.             }
  141.             if (getter == null)
  142.                 getter = this.GetGetMethod(false);
  143.             if (getter != null) {
  144.                 try {
  145.                     return getter.Invoke(obj, invokeAttr, binder, index == null ? new object[0] : index, culture);
  146.                 }
  147.                 catch (TargetInvocationException e) {
  148.                     throw e.InnerException;
  149.                 }
  150.             }
  151.             else
  152.                 return Missing.Value;
  153.         }
  154.        
  155.         public override MethodInfo[] GetAccessors(bool nonPublic)
  156.         {
  157.             if (this.getter != null && (nonPublic || this.getter.IsPublic))
  158.                 if (this.setter != null && (nonPublic || this.setter.IsPublic))
  159.                     return new MethodInfo[] {this.getter, this.setter};
  160.                 else
  161.                     return new MethodInfo[] {this.getter};
  162.             else if (this.setter != null && (nonPublic || this.setter.IsPublic))
  163.                 return new MethodInfo[] {this.setter};
  164.             else
  165.                 return new MethodInfo[] {};
  166.         }
  167.        
  168.         static internal MethodInfo GetGetMethod(PropertyInfo prop, bool nonPublic)
  169.         {
  170.             if (prop == null)
  171.                 return null;
  172.             JSProperty jsprop = prop as JSProperty;
  173.             if (jsprop != null)
  174.                 return jsprop.GetGetMethod(nonPublic);
  175.             MethodInfo meth = prop.GetGetMethod(nonPublic);
  176.             if (meth != null)
  177.                 return meth;
  178.             Type pdt = prop.DeclaringType;
  179.             if (pdt == null)
  180.                 return null;
  181.             Type bt = pdt.BaseType;
  182.             if (bt == null)
  183.                 return null;
  184.             meth = prop.GetGetMethod(nonPublic);
  185.             if (meth == null)
  186.                 return null;
  187.             BindingFlags flags = BindingFlags.Public;
  188.             if (meth.IsStatic)
  189.                 flags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
  190.             else
  191.                 flags |= BindingFlags.Instance;
  192.             if (nonPublic)
  193.                 flags |= BindingFlags.NonPublic;
  194.             string pname = prop.Name;
  195.             prop = null;
  196.             try {
  197.                 prop = bt.GetProperty(pname, flags, null, null, new Type[] {}, null);
  198.             }
  199.             catch (AmbiguousMatchException) {
  200.             }
  201.             if (prop != null)
  202.                 return JSProperty.GetGetMethod(prop, nonPublic);
  203.             return null;
  204.         }
  205.        
  206.         public override MethodInfo GetGetMethod(bool nonPublic)
  207.         {
  208.             if (this.getter == null) {
  209.                 try {
  210.                     IReflect ir = ((ClassScope)this.setter.obj).GetSuperType();
  211.                     BindingFlags flags = BindingFlags.Public;
  212.                     if (this.setter.IsStatic)
  213.                         flags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
  214.                     else
  215.                         flags |= BindingFlags.Instance;
  216.                     if (nonPublic)
  217.                         flags |= BindingFlags.NonPublic;
  218.                     PropertyInfo prop = ir.GetProperty(this.name, flags, null, null, new Type[] {}, null);
  219.                     if (prop is JSProperty)
  220.                         return prop.GetGetMethod(nonPublic);
  221.                     else
  222.                         return JSProperty.GetGetMethod(prop, nonPublic);
  223.                 }
  224.                 catch (AmbiguousMatchException) {
  225.                 }
  226.             }
  227.             if (nonPublic || this.getter.IsPublic)
  228.                 return this.getter;
  229.             else
  230.                 return null;
  231.         }
  232.        
  233.         public override ParameterInfo[] GetIndexParameters()
  234.         {
  235.             if (this.formal_parameters == null) {
  236.                 if (this.getter != null)
  237.                     this.formal_parameters = this.getter.GetParameters();
  238.                 else {
  239.                     ParameterInfo[] setterPars = this.setter.GetParameters();
  240.                     int n = setterPars.Length;
  241.                     if (n <= 1)
  242.                         n = 1;
  243.                     this.formal_parameters = new ParameterInfo[n - 1];
  244.                     for (int i = 0; i < n - 1; i++)
  245.                         this.formal_parameters[i] = setterPars[i];
  246.                 }
  247.             }
  248.             return this.formal_parameters;
  249.         }
  250.        
  251.         static internal MethodInfo GetSetMethod(PropertyInfo prop, bool nonPublic)
  252.         {
  253.             if (prop == null)
  254.                 return null;
  255.             JSProperty jsProp = prop as JSProperty;
  256.             if (jsProp != null)
  257.                 return jsProp.GetSetMethod(nonPublic);
  258.             MethodInfo meth = prop.GetSetMethod(nonPublic);
  259.             if (meth != null)
  260.                 return meth;
  261.             Type pdt = prop.DeclaringType;
  262.             if (pdt == null)
  263.                 return null;
  264.             Type bt = pdt.BaseType;
  265.             if (bt == null)
  266.                 return null;
  267.             meth = prop.GetGetMethod(nonPublic);
  268.             if (meth == null)
  269.                 return null;
  270.             BindingFlags flags = BindingFlags.Public;
  271.             if (meth.IsStatic)
  272.                 flags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
  273.             else
  274.                 flags |= BindingFlags.Instance;
  275.             if (nonPublic)
  276.                 flags |= BindingFlags.NonPublic;
  277.             string pname = prop.Name;
  278.             prop = null;
  279.             try {
  280.                 prop = bt.GetProperty(pname, flags, null, null, new Type[] {}, null);
  281.             }
  282.             catch (AmbiguousMatchException) {
  283.             }
  284.             if (prop != null)
  285.                 return JSProperty.GetSetMethod(prop, nonPublic);
  286.             return null;
  287.         }
  288.        
  289.         public override MethodInfo GetSetMethod(bool nonPublic)
  290.         {
  291.             if (this.setter == null) {
  292.                 try {
  293.                     IReflect ir = ((ClassScope)this.getter.obj).GetSuperType();
  294.                     BindingFlags flags = BindingFlags.Public;
  295.                     if (this.getter.IsStatic)
  296.                         flags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
  297.                     else
  298.                         flags |= BindingFlags.Instance;
  299.                     if (nonPublic)
  300.                         flags |= BindingFlags.NonPublic;
  301.                     PropertyInfo prop = ir.GetProperty(this.name, flags, null, null, new Type[] {}, null);
  302.                     if (prop is JSProperty)
  303.                         return prop.GetSetMethod(nonPublic);
  304.                     else
  305.                         return JSProperty.GetSetMethod(prop, nonPublic);
  306.                 }
  307.                 catch (AmbiguousMatchException) {
  308.                 }
  309.             }
  310.             if (nonPublic || this.setter.IsPublic)
  311.                 return this.setter;
  312.             else
  313.                 return null;
  314.         }
  315.        
  316.         public override sealed bool IsDefined(Type type, bool inherit)
  317.         {
  318.             return false;
  319.         }
  320.        
  321.         public override MemberTypes MemberType {
  322.             get { return MemberTypes.Property; }
  323.         }
  324.        
  325.         public override string Name {
  326.             get { return this.name; }
  327.         }
  328.        
  329.         internal IReflect PropertyIR()
  330.         {
  331.             if (this.getter is JSFieldMethod)
  332.                 return ((JSFieldMethod)this.getter).ReturnIR();
  333.             if (this.setter != null) {
  334.                 ParameterInfo[] pars = this.setter.GetParameters();
  335.                 if (pars.Length > 0) {
  336.                     ParameterInfo par = pars[pars.Length - 1];
  337.                     if (par is ParameterDeclaration)
  338.                         return ((ParameterDeclaration)par).ParameterIReflect;
  339.                     else
  340.                         return par.ParameterType;
  341.                 }
  342.             }
  343.             return Typeob.Void;
  344.         }
  345.        
  346.         public override Type PropertyType {
  347.             get {
  348.                 if (this.getter != null)
  349.                     return this.getter.ReturnType;
  350.                 if (this.setter != null) {
  351.                     ParameterInfo[] pars = this.setter.GetParameters();
  352.                     if (pars.Length > 0)
  353.                         return pars[pars.Length - 1].ParameterType;
  354.                 }
  355.                 return Typeob.Void;
  356.             }
  357.         }
  358.        
  359.         public override Type ReflectedType {
  360.             get {
  361.                 if (this.getter != null)
  362.                     return this.getter.ReflectedType;
  363.                 else
  364.                     return this.setter.ReflectedType;
  365.             }
  366.         }
  367.        
  368.         #if !DEBUG
  369.         [DebuggerStepThroughAttribute()]
  370.         [DebuggerHiddenAttribute()]
  371.         #endif
  372.         static internal void SetValue(PropertyInfo prop, object obj, object value, object[] index)
  373.         {
  374.             JSProperty jsprop = prop as JSProperty;
  375.             if (jsprop != null) {
  376.                 jsprop.SetValue(obj, value, BindingFlags.ExactBinding, null, index, null);
  377.                 return;
  378.             }
  379.             MethodInfo meth = JSProperty.GetSetMethod(prop, false);
  380.             if (meth != null) {
  381.                 int n = (index == null ? 0 : index.Length);
  382.                 object[] args = new object[n + 1];
  383.                 if (n > 0)
  384.                     ArrayObject.Copy(index, 0, args, 0, n);
  385.                 args[n] = value;
  386.                 meth.Invoke(obj, BindingFlags.ExactBinding, null, args, null);
  387.                 return;
  388.             }
  389.             throw new MissingMethodException();
  390.         }
  391.        
  392.         #if !DEBUG
  393.         [DebuggerStepThroughAttribute()]
  394.         [DebuggerHiddenAttribute()]
  395.         #endif
  396.         public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
  397.         {
  398.             MethodInfo setter = this.setter;
  399.             JSObject jsOb = obj as JSObject;
  400.             if (setter == null && jsOb != null) {
  401.                 setter = jsOb.GetMethod("set_" + this.name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  402.                 JSWrappedMethod wrm = setter as JSWrappedMethod;
  403.                 if (wrm != null)
  404.                     setter = wrm.method;
  405.             }
  406.             if (setter == null)
  407.                 setter = this.GetSetMethod(false);
  408.             if (setter != null) {
  409.                 if (index == null || index.Length == 0)
  410.                     setter.Invoke(obj, invokeAttr, binder, new object[] {value}, culture);
  411.                 else {
  412.                     int n = index.Length;
  413.                     object[] args = new object[n + 1];
  414.                     ArrayObject.Copy(index, 0, args, 0, n);
  415.                     args[n] = value;
  416.                     setter.Invoke(obj, invokeAttr, binder, args, culture);
  417.                 }
  418.             }
  419.         }
  420.        
  421.     }
  422. }

Developer Fusion