/// <summary> /// Called when a set is attempting to assign to a field or property from a derived class through the base class. /// /// The default behavior is to allow the assignment. /// </summary> public virtual ErrorInfo MakeStaticAssignFromDerivedTypeError(Type accessingType, DynamicMetaObject self, MemberTracker assigning, DynamicMetaObject assignedValue, OverloadResolverFactory context) { switch (assigning.MemberType) { case TrackerTypes.Property: PropertyTracker pt = (PropertyTracker)assigning; MethodInfo setter = pt.GetSetMethod() ?? pt.GetSetMethod(true); return(ErrorInfo.FromValueNoError( AstUtils.SimpleCallHelper( setter, ConvertExpression( assignedValue.Expression, setter.GetParameters()[0].ParameterType, ConversionResultKind.ExplicitCast, context ) ) )); case TrackerTypes.Field: FieldTracker ft = (FieldTracker)assigning; return(ErrorInfo.FromValueNoError( Expression.Assign( Expression.Field(null, ft.Field), ConvertExpression(assignedValue.Expression, ft.FieldType, ConversionResultKind.ExplicitCast, context) ) )); default: throw new InvalidOperationException(); } }
private void MakePropertyRule(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type targetType, MemberGroup properties, DynamicMetaObject errorSuggestion) { PropertyTracker info = (PropertyTracker)properties[0]; MethodInfo setter = info.GetSetMethod(true); // Allow access to protected getters TODO: this should go, it supports IronPython semantics. if (setter != null && !setter.IsPublic && !setter.IsProtected()) { if (!PrivateBinding) { setter = null; } } if (setter != null) { setter = CompilerHelpers.GetCallableMethod(setter, PrivateBinding); if (info.IsStatic != (instance == null)) { memInfo.Body.FinishCondition( errorSuggestion ?? MakeError( MakeStaticPropertyInstanceAccessError( info, true, instance, target ), typeof(object) ) ); } else if (info.IsStatic && info.DeclaringType != targetType) { memInfo.Body.FinishCondition( errorSuggestion ?? MakeError( MakeStaticAssignFromDerivedTypeError(targetType, instance, info, target, memInfo.ResolutionFactory), typeof(object) ) ); } else if (setter.ContainsGenericParameters) { memInfo.Body.FinishCondition( MakeGenericPropertyExpression(memInfo) ); } else if (setter.IsPublic && !setter.DeclaringType.IsValueType) { if (instance == null) { memInfo.Body.FinishCondition( Ast.Block( AstUtils.SimpleCallHelper( setter, ConvertExpression( target.Expression, setter.GetParameters()[0].ParameterType, ConversionResultKind.ExplicitCast, memInfo.ResolutionFactory ) ), Ast.Constant(null) ) ); } else { memInfo.Body.FinishCondition( MakeReturnValue( MakeCallExpression(memInfo.ResolutionFactory, setter, instance, target), target ) ); } } else { // TODO: Should be able to do better w/ value types. memInfo.Body.FinishCondition( MakeReturnValue( Ast.Call( AstUtils.Constant(((ReflectedPropertyTracker)info).Property), // TODO: Private binding on extension properties typeof(PropertyInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object), typeof(object[]) }), instance == null ? AstUtils.Constant(null) : AstUtils.Convert(instance.Expression, typeof(object)), AstUtils.Convert( ConvertExpression( target.Expression, setter.GetParameters()[0].ParameterType, ConversionResultKind.ExplicitCast, memInfo.ResolutionFactory ), typeof(object) ), Ast.NewArrayInit(typeof(object)) ), target ) ); } } else { memInfo.Body.FinishCondition( errorSuggestion ?? MakeError( MakeMissingMemberErrorForAssignReadOnlyProperty(targetType, instance, memInfo.Name), typeof(object) ) ); } }
private void MakePropertyRule(Type targetType, MemberGroup properties) { PropertyTracker info = (PropertyTracker)properties[0]; MethodInfo setter = info.GetSetMethod(true); // Allow access to protected getters TODO: this should go, it supports IronPython semantics. if (setter != null && !setter.IsPublic && !(setter.IsFamily || setter.IsFamilyOrAssembly)) { if (!ScriptDomainManager.Options.PrivateBinding) { setter = null; } } if (setter != null) { setter = CompilerHelpers.GetCallableMethod(setter); if (info.IsStatic != _isStatic) { // TODO: Too python specific AddToBody(Binder.MakeReadOnlyMemberError(Rule, targetType, StringName)); } else if (setter.ContainsGenericParameters) { AddToBody(Rule.MakeError(MakeGenericPropertyExpression())); } else if (setter.IsPublic && !setter.DeclaringType.IsValueType) { if (_isStatic) { AddToBody( Rule.MakeReturn( Binder, Ast.SimpleCallHelper( setter, Binder.ConvertExpression( Rule.Parameters[1], setter.GetParameters()[0].ParameterType ) ) ) ); } else { AddToBody(Rule.MakeReturn(Binder, MakeReturnValue(Binder.MakeCallExpression(setter, Rule.Parameters)))); } } else { // TODO: Should be able to do better w/ value types. AddToBody( Rule.MakeReturn( Binder, MakeReturnValue( Ast.Call( Ast.RuntimeConstant(((ReflectedPropertyTracker)info).Property), // TODO: Private binding on extension properties typeof(PropertyInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object), typeof(object[]) }), Ast.ConvertHelper(Instance, typeof(object)), Ast.ConvertHelper(Rule.Parameters[1], typeof(object)), Ast.NewArray(typeof(object[])) ) ) ) ); } } else { AddToBody(Binder.MakeMissingMemberError(Rule, targetType, StringName)); } }
internal static ReflectedGetterSetter GetReflectedProperty(PropertyTracker pt, MemberGroup allProperties, bool privateBinding) { ReflectedGetterSetter rp; lock (_propertyCache) { if (_propertyCache.TryGetValue(pt, out rp)) { return rp; } NameType nt = NameType.PythonProperty; MethodInfo getter = FilterProtectedGetterOrSetter(pt.GetGetMethod(true), privateBinding); MethodInfo setter = FilterProtectedGetterOrSetter(pt.GetSetMethod(true), privateBinding); if ((getter != null && getter.IsDefined(typeof(PythonHiddenAttribute), true)) || setter != null && setter.IsDefined(typeof(PythonHiddenAttribute), true)) { nt = NameType.Property; } ExtensionPropertyTracker ept = pt as ExtensionPropertyTracker; if (ept == null) { ReflectedPropertyTracker rpt = pt as ReflectedPropertyTracker; Debug.Assert(rpt != null); if (PythonBinder.IsExtendedType(pt.DeclaringType) || rpt.Property.IsDefined(typeof(PythonHiddenAttribute), true)) { nt = NameType.Property; } if (pt.GetIndexParameters().Length == 0) { List<MethodInfo> getters = new List<MethodInfo>(); List<MethodInfo> setters = new List<MethodInfo>(); IList<ExtensionPropertyTracker> overriddenProperties = NewTypeMaker.GetOverriddenProperties((getter ?? setter).DeclaringType, pt.Name); foreach (ExtensionPropertyTracker tracker in overriddenProperties) { MethodInfo method = tracker.GetGetMethod(privateBinding); if (method != null) { getters.Add(method); } method = tracker.GetSetMethod(privateBinding); if (method != null) { setters.Add(method); } } foreach (PropertyTracker propTracker in allProperties) { MethodInfo method = propTracker.GetGetMethod(privateBinding); if (method != null) { getters.Add(method); } method = propTracker.GetSetMethod(privateBinding); if (method != null) { setters.Add(method); } } rp = new ReflectedProperty(rpt.Property, getters.ToArray(), setters.ToArray(), nt); } else { rp = new ReflectedIndexer(((ReflectedPropertyTracker)pt).Property, NameType.Property, privateBinding); } } else { rp = new ReflectedExtensionProperty(new ExtensionPropertyInfo(pt.DeclaringType, getter ?? setter), nt); } _propertyCache[pt] = rp; return rp; } }
private void MakePropertyRule(Type targetType, MemberGroup properties) { PropertyTracker info = (PropertyTracker)properties[0]; MethodInfo setter = info.GetSetMethod(true); // Allow access to protected getters TODO: this should go, it supports IronPython semantics. if (setter != null && !setter.IsPublic && !(setter.IsFamily || setter.IsFamilyOrAssembly)) { if (!PrivateBinding) { setter = null; } } if (setter != null) { setter = CompilerHelpers.GetCallableMethod(setter, Binder.PrivateBinding); if (info.IsStatic != _isStatic) { AddToBody(Binder.MakeStaticPropertyInstanceAccessError(info, true, Rule.Parameters).MakeErrorForRule(Rule, Binder)); } else if (info.IsStatic && info.DeclaringType != targetType) { AddToBody(Binder.MakeStaticAssignFromDerivedTypeError(targetType, info, Rule.Parameters[1], Rule.Context).MakeErrorForRule(Rule, Binder)); } else if (setter.ContainsGenericParameters) { AddToBody(Rule.MakeError(MakeGenericPropertyExpression())); } else if (setter.IsPublic && !setter.DeclaringType.IsValueType) { if (_isStatic) { AddToBody( Rule.MakeReturn( Binder, AstUtils.SimpleCallHelper( setter, Binder.ConvertExpression( Rule.Parameters[1], setter.GetParameters()[0].ParameterType, ConversionResultKind.ExplicitCast, Rule.Context ) ) ) ); } else { AddToBody(Rule.MakeReturn(Binder, MakeReturnValue(Binder.MakeCallExpression(Rule.Context, setter, Rule.Parameters)))); } } else { // TODO: Should be able to do better w/ value types. AddToBody( Rule.MakeReturn( Binder, MakeReturnValue( Ast.Call( Ast.Constant(((ReflectedPropertyTracker)info).Property), // TODO: Private binding on extension properties typeof(PropertyInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object), typeof(object[]) }), AstUtils.Convert(Instance, typeof(object)), AstUtils.Convert(Rule.Parameters[1], typeof(object)), Ast.NewArrayInit(typeof(object)) ) ) ) ); } } else { AddToBody(Binder.MakeMissingMemberError(targetType, StringName).MakeErrorForRule(Rule, Binder)); } }