private DynamicMetaObject MakeDeleteMemberTarget(SetOrDeleteMemberInfo delInfo, DynamicMetaObject target, DynamicMetaObject errorSuggestion) { Type type = target.GetLimitType(); BindingRestrictions restrictions = target.Restrictions; DynamicMetaObject self = target; if (typeof(TypeTracker).IsAssignableFrom(type)) { restrictions = restrictions.Merge( BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value) ); type = ((TypeTracker)target.Value).Type; self = null; } delInfo.Body.Restrictions = restrictions; if (self == null || !MakeOperatorDeleteMemberBody(delInfo, self, type, "DeleteMember")) { MemberGroup group = GetMember(MemberRequestKind.Delete, type, delInfo.Name); if (group.Count != 0) { if (group[0].MemberType == TrackerTypes.Property) { MethodInfo del = ((PropertyTracker)group[0]).GetDeleteMethod(PrivateBinding); if (del != null) { MakePropertyDeleteStatement(delInfo, self, del); return delInfo.Body.GetMetaObject(target); } } delInfo.Body.FinishCondition(errorSuggestion ?? MakeError(MakeUndeletableMemberError(GetDeclaringMemberType(group), delInfo.Name), typeof(void))); } else { delInfo.Body.FinishCondition(errorSuggestion ?? MakeError(MakeMissingMemberErrorForDelete(type, self, delInfo.Name), typeof(void))); } } return delInfo.Body.GetMetaObject(target); }
private void MakeSetMemberRule(SetOrDeleteMemberInfo memInfo, Type type, DynamicMetaObject self, DynamicMetaObject value) { if (MakeOperatorSetMemberBody(memInfo, self, value, type, "SetMember")) { return; } MemberGroup members = GetMember(MemberRequestKind.Set, type, memInfo.Name); // if lookup failed try the strong-box type if available. if (self != null && members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type)) { self = new DynamicMetaObject(Ast.Field(AstUtils.Convert(self.Expression, type), type.GetField("Value")), BindingRestrictions.Empty, ((IStrongBox)self.Value).Value); type = type.GetGenericArguments()[0]; members = GetMember(MemberRequestKind.Set, type, memInfo.Name); } Expression error; TrackerTypes memberTypes = GetMemberType(members, out error); if (error == null) { switch (memberTypes) { case TrackerTypes.Method: case TrackerTypes.TypeGroup: case TrackerTypes.Type: case TrackerTypes.Constructor: memInfo.Body.FinishCondition( MakeError(MakeReadOnlyMemberError(type, memInfo.Name), BindingRestrictions.Empty, typeof(object)) ); break; case TrackerTypes.Event: memInfo.Body.FinishCondition( MakeError(MakeEventValidation(members, self, value, memInfo.ResolutionFactory), BindingRestrictions.Empty, typeof(object)) ); break; case TrackerTypes.Field: MakeFieldRule(memInfo, self, value, type, members); break; case TrackerTypes.Property: MakePropertyRule(memInfo, self, value, type, members); break; case TrackerTypes.Custom: MakeGenericBody(memInfo, self, value, type, members[0]); break; case TrackerTypes.All: // no match if (MakeOperatorSetMemberBody(memInfo, self, value, type, "SetMemberAfter")) { return; } memInfo.Body.FinishCondition( MakeError(MakeMissingMemberErrorForAssign(type, self, memInfo.Name), BindingRestrictions.Empty, typeof(object)) ); break; default: throw new InvalidOperationException(); } } else { memInfo.Body.FinishCondition(error); } }
private DynamicMetaObject MakeDeleteMemberTarget(SetOrDeleteMemberInfo delInfo, DynamicMetaObject target) { Type type = target.GetLimitType(); BindingRestrictions restrictions = target.Restrictions; Expression self = target.Expression; // needed for DeleteMember call until DynamicAction goes away OldDynamicAction act = OldDeleteMemberAction.Make( this, delInfo.Name ); if (typeof(TypeTracker).IsAssignableFrom(type)) { restrictions = restrictions.Merge( BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value) ); type = ((TypeTracker)target.Value).Type; self = null; } delInfo.Body.Restrictions = restrictions; if (self == null || !MakeOperatorDeleteMemberBody(delInfo, self, type, "DeleteMember")) { MemberGroup group = GetMember(act, type, delInfo.Name); if (group.Count != 0) { if (group[0].MemberType == TrackerTypes.Property) { MethodInfo del = ((PropertyTracker)group[0]).GetDeleteMethod(PrivateBinding); if (del != null) { MakePropertyDeleteStatement(delInfo, self, del); return delInfo.Body.GetMetaObject(target); } } delInfo.Body.FinishCondition(MakeError(MakeUndeletableMemberError(GetDeclaringMemberType(group), delInfo.Name))); } else { delInfo.Body.FinishCondition(MakeError(MakeMissingMemberError(type, delInfo.Name))); } } return delInfo.Body.GetMetaObject(target); }
private DynamicMetaObject MakeSetMemberTarget(SetOrDeleteMemberInfo memInfo, DynamicMetaObject target, DynamicMetaObject value) { Type type = target.GetLimitType(); Expression self = target.Expression; target = target.Restrict(target.GetLimitType()); memInfo.Body.Restrictions = target.Restrictions; if (typeof(TypeTracker).IsAssignableFrom(type)) { type = ((TypeTracker)target.Value).Type; self = null; memInfo.Body.Restrictions = memInfo.Body.Restrictions.Merge( BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value) ); } MakeSetMemberRule(memInfo, type, self, value); return memInfo.Body.GetMetaObject(target, value); }
private void MakeFieldRule(SetOrDeleteMemberInfo memInfo, Expression instance, DynamicMetaObject target, Type targetType, MemberGroup fields) { FieldTracker field = (FieldTracker)fields[0]; // TODO: Tmp variable for target if (field.DeclaringType.IsGenericType && field.DeclaringType.GetGenericTypeDefinition() == typeof(StrongBox<>)) { // work around a CLR bug where we can't access generic fields from dynamic methods. Type[] generic = field.DeclaringType.GetGenericArguments(); memInfo.Body.FinishCondition( MakeReturnValue( Ast.Assign( Ast.Field( AstUtils.Convert(instance, field.DeclaringType), field.DeclaringType.GetField("Value") ), AstUtils.Convert(target.Expression, generic[0]) ), target ) ); } else if (field.IsInitOnly || field.IsLiteral) { memInfo.Body.FinishCondition( MakeError( MakeReadOnlyMemberError(targetType, memInfo.Name), typeof(object) ) ); } else if (field.IsStatic && targetType != field.DeclaringType) { memInfo.Body.FinishCondition( MakeError( MakeStaticAssignFromDerivedTypeError(targetType, field, target.Expression, memInfo.CodeContext), typeof(object) ) ); } else if (field.DeclaringType.IsValueType && !field.IsStatic) { memInfo.Body.FinishCondition( Ast.Throw( Ast.New( typeof(ArgumentException).GetConstructor(new Type[] { typeof(string) }), AstUtils.Constant("cannot assign to value types") ), typeof(object) ) ); } else if (field.IsPublic && field.DeclaringType.IsVisible) { memInfo.Body.FinishCondition( MakeReturnValue( Ast.Assign( Ast.Field( field.IsStatic ? null : AstUtils.Convert(instance, field.DeclaringType), field.Field ), ConvertExpression(target.Expression, field.FieldType, ConversionResultKind.ExplicitCast, memInfo.CodeContext) ), target ) ); } else { memInfo.Body.FinishCondition( MakeReturnValue( Ast.Call( AstUtils.Convert(AstUtils.Constant(field.Field), typeof(FieldInfo)), typeof(FieldInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object) }), field.IsStatic ? AstUtils.Constant(null) : (Expression)AstUtils.Convert(instance, typeof(object)), AstUtils.Convert(target.Expression, typeof(object)) ), target ) ); } }
/// <summary> if a member-injector is defined-on or registered-for this type call it </summary> private bool MakeOperatorSetMemberBody(SetOrDeleteMemberInfo memInfo, Expression self, DynamicMetaObject target, Type type, string name) { if (self != null) { MethodInfo setMem = GetMethod(type, name); if (setMem != null && setMem.IsSpecialName) { ParameterExpression tmp = Ast.Variable(target.Expression.Type, "setValue"); memInfo.Body.AddVariable(tmp); Expression call = MakeCallExpression(memInfo.CodeContext, setMem, AstUtils.Convert(self, type), AstUtils.Constant(memInfo.Name), tmp); call = Ast.Block(Ast.Assign(tmp, target.Expression), call); if (setMem.ReturnType == typeof(bool)) { memInfo.Body.AddCondition( call, tmp ); } else { memInfo.Body.FinishCondition(Ast.Block(call, AstUtils.Convert(tmp, typeof(object)))); } return setMem.ReturnType != typeof(bool); } } return false; }
private void MakeGenericBody(SetOrDeleteMemberInfo memInfo, Expression instance, DynamicMetaObject target, Type type, MemberTracker tracker) { if (instance != null) { tracker = tracker.BindToInstance(instance); } Expression val = tracker.SetValue(memInfo.CodeContext, this, type, target.Expression); if (val != null) { memInfo.Body.FinishCondition(val); } else { memInfo.Body.FinishCondition( MakeError(tracker.GetError(this), typeof(object)) ); } }
private void MakePropertyRule(SetOrDeleteMemberInfo memInfo, Expression instance, DynamicMetaObject target, 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.IsProtected()) { if (!PrivateBinding) { setter = null; } } if (setter != null) { setter = CompilerHelpers.GetCallableMethod(setter, PrivateBinding); if (info.IsStatic != (instance == null)) { memInfo.Body.FinishCondition( MakeError( MakeStaticPropertyInstanceAccessError( info, true, instance, target.Expression ), typeof(object) ) ); } else if (info.IsStatic && info.DeclaringType != targetType) { memInfo.Body.FinishCondition( MakeError( MakeStaticAssignFromDerivedTypeError(targetType, info, target.Expression, memInfo.CodeContext), 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.CodeContext ) ), Ast.Constant(null) ) ); } else { memInfo.Body.FinishCondition( MakeReturnValue( MakeCallExpression(memInfo.CodeContext, setter, instance, target.Expression), 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, typeof(object)), AstUtils.Convert( ConvertExpression( target.Expression, setter.GetParameters()[0].ParameterType, ConversionResultKind.ExplicitCast, memInfo.CodeContext ), typeof(object) ), Ast.NewArrayInit(typeof(object)) ), target ) ); } } else { memInfo.Body.FinishCondition( MakeError( MakeMissingMemberError(targetType, memInfo.Name), typeof(object) ) ); } }
private void MakePropertyDeleteStatement(SetOrDeleteMemberInfo delInfo, DynamicMetaObject instance, MethodInfo delete) { delInfo.Body.FinishCondition( instance == null ? MakeCallExpression(delInfo.ResolutionFactory, delete) : MakeCallExpression(delInfo.ResolutionFactory, delete, instance) ); }
private void MakeSetMemberRule(SetOrDeleteMemberInfo memInfo, Type type, Expression self, DynamicMetaObject target) { if (MakeOperatorSetMemberBody(memInfo, self, target, type, "SetMember")) { return; } // needed for GetMember call until DynamicAction goes away OldDynamicAction act = OldSetMemberAction.Make( this, memInfo.Name ); MemberGroup members = GetMember(act, type, memInfo.Name); // if lookup failed try the strong-box type if available. if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type)) { self = Ast.Field(AstUtils.Convert(self, type), type.GetField("Value")); type = type.GetGenericArguments()[0]; members = GetMember(act, type, memInfo.Name); } Expression error; TrackerTypes memberTypes = GetMemberType(members, out error); if (error == null) { switch (memberTypes) { case TrackerTypes.Method: case TrackerTypes.TypeGroup: case TrackerTypes.Type: case TrackerTypes.Constructor: memInfo.Body.FinishCondition( MakeError(MakeReadOnlyMemberError(type, memInfo.Name), typeof(object)) ); break; case TrackerTypes.Event: memInfo.Body.FinishCondition( MakeError(MakeEventValidation(members, self, target.Expression, memInfo.CodeContext), typeof(object)) ); break; case TrackerTypes.Field: MakeFieldRule(memInfo, self, target, type, members); break; case TrackerTypes.Property: MakePropertyRule(memInfo, self, target, type, members); break; case TrackerTypes.Custom: MakeGenericBody(memInfo, self, target, type, members[0]); break; case TrackerTypes.All: // no match if (MakeOperatorSetMemberBody(memInfo, self, target, type, "SetMemberAfter")) { return; } memInfo.Body.FinishCondition( MakeError(MakeMissingMemberError(type, memInfo.Name), typeof(object)) ); break; default: throw new InvalidOperationException(); } } else { memInfo.Body.FinishCondition(error); } }
/// <summary> if a member-injector is defined-on or registered-for this type call it </summary> private bool MakeOperatorDeleteMemberBody(SetOrDeleteMemberInfo delInfo, DynamicMetaObject instance, Type type, string name) { MethodInfo delMem = GetMethod(type, name); if (delMem != null) { DynamicMetaObject call = MakeCallExpression(delInfo.ResolutionFactory, delMem, instance, new DynamicMetaObject(AstUtils.Constant(delInfo.Name), BindingRestrictions.Empty, delInfo.Name)); if (delMem.ReturnType == typeof(bool)) { delInfo.Body.AddCondition( call.Expression, AstUtils.Constant(null) ); } else { delInfo.Body.FinishCondition(call); } return delMem.ReturnType != typeof(bool); } return false; }
private void MakeGenericBody(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type type, MemberTracker tracker, DynamicMetaObject errorSuggestion) { if (instance != null) { tracker = tracker.BindToInstance(instance); } DynamicMetaObject val = tracker.SetValue(memInfo.ResolutionFactory, this, type, target, errorSuggestion); if (val != null) { memInfo.Body.FinishCondition(val); } else { memInfo.Body.FinishCondition( MakeError(tracker.GetError(this), typeof(object)) ); } }
/// <summary> if a member-injector is defined-on or registered-for this type call it </summary> private bool MakeOperatorDeleteMemberBody(SetOrDeleteMemberInfo delInfo, Expression instance, Type type, string name) { MethodInfo delMem = GetMethod(type, name); if (delMem != null && delMem.IsSpecialName) { Expression call = MakeCallExpression(delInfo.CodeContext, delMem, instance, Ast.Constant(delInfo.Name)); if (delMem.ReturnType == typeof(bool)) { delInfo.Body.AddCondition( call, Ast.Constant(null) ); } else { delInfo.Body.FinishCondition(call); } return delMem.ReturnType != typeof(bool); } return false; }
private void MakeSetMemberRule(SetOrDeleteMemberInfo memInfo, Type type, Expression self, MetaObject target) { if (MakeOperatorSetMemberBody(memInfo, self, target, type, "SetMember")) { return; } // needed for GetMember call until DynamicAction goes away OldDynamicAction act = OldSetMemberAction.Make( this, memInfo.Name ); MemberGroup members = GetMember(act, type, memInfo.Name); // if lookup failed try the strong-box type if available. if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type)) { self = Ast.Field(AstUtils.Convert(self, type), type.GetField("Value")); type = type.GetGenericArguments()[0]; members = GetMember(act, type, memInfo.Name); } Expression error; TrackerTypes memberTypes = GetMemberType(members, out error); if (error == null) { switch (memberTypes) { case TrackerTypes.Method: case TrackerTypes.TypeGroup: case TrackerTypes.Type: case TrackerTypes.Constructor: memInfo.Body.FinishCondition( MakeError(MakeReadOnlyMemberError(type, memInfo.Name)) ); break; case TrackerTypes.Event: memInfo.Body.FinishCondition( MakeError(MakeEventValidation(members, self, target.Expression, memInfo.CodeContext)) ); break; case TrackerTypes.Field: MakeFieldRule(memInfo, self, target, type, members); break; case TrackerTypes.Property: MakePropertyRule(memInfo, self, target, type, members); break; case TrackerTypes.Custom: MakeGenericBody(memInfo, self, target, type, members[0]); break; case TrackerTypes.All: // no match if (MakeOperatorSetMemberBody(memInfo, self, target, type, "SetMemberAfter")) { return; } memInfo.Body.FinishCondition( MakeError(MakeMissingMemberError(type, memInfo.Name)) ); break; default: throw new InvalidOperationException(); } } else { memInfo.Body.FinishCondition(error); } }
private void MakePropertyDeleteStatement(SetOrDeleteMemberInfo delInfo, Expression instance, MethodInfo delete) { delInfo.Body.FinishCondition( MakeCallExpression(delInfo.CodeContext, delete, instance) ); }
private void MakeSetMemberRule(SetOrDeleteMemberInfo memInfo, Type type, DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { if (MakeOperatorSetMemberBody(memInfo, self, value, type, "SetMember")) { return; } MemberGroup members = GetMember(MemberRequestKind.Set, type, memInfo.Name); // if lookup failed try the strong-box type if available. if (self != null && members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type)) { self = new DynamicMetaObject(Ast.Field(AstUtils.Convert(self.Expression, type), type.GetInheritedFields("Value").First()), BindingRestrictions.Empty, ((IStrongBox)self.Value).Value); type = type.GetGenericArguments()[0]; members = GetMember(MemberRequestKind.Set, type, memInfo.Name); } Expression error; TrackerTypes memberTypes = GetMemberType(members, out error); if (error == null) { switch (memberTypes) { case TrackerTypes.Method: case TrackerTypes.TypeGroup: case TrackerTypes.Type: case TrackerTypes.Constructor: memInfo.Body.FinishError( errorSuggestion ?? MakeError(MakeReadOnlyMemberError(type, memInfo.Name), BindingRestrictions.Empty, typeof(object)) ); break; case TrackerTypes.Event: memInfo.Body.FinishError( errorSuggestion ?? MakeError(MakeEventValidation(members, self, value, memInfo.ResolutionFactory), BindingRestrictions.Empty, typeof(object)) ); break; case TrackerTypes.Field: MakeFieldRule(memInfo, self, value, type, members, errorSuggestion); break; case TrackerTypes.Property: MakePropertyRule(memInfo, self, value, type, members, errorSuggestion); break; case TrackerTypes.Custom: MakeGenericBody(memInfo, self, value, type, members[0], errorSuggestion); break; case TrackerTypes.All: // no match if (MakeOperatorSetMemberBody(memInfo, self, value, type, "SetMemberAfter")) { return; } memInfo.Body.FinishError( errorSuggestion ?? MakeError(MakeMissingMemberErrorForAssign(type, self, memInfo.Name), BindingRestrictions.Empty, typeof(object)) ); break; default: throw new InvalidOperationException(); } } else { memInfo.Body.FinishError(error); } }
/// <summary> if a member-injector is defined-on or registered-for this type call it </summary> private bool MakeOperatorSetMemberBody(SetOrDeleteMemberInfo memInfo, DynamicMetaObject self, DynamicMetaObject target, Type type, string name) { if (self != null) { MethodInfo setMem = GetMethod(type, name); if (setMem != null) { ParameterExpression tmp = Ast.Variable(target.Expression.Type, "setValue"); memInfo.Body.AddVariable(tmp); var callMo = MakeCallExpression( memInfo.ResolutionFactory, setMem, self.Clone(AstUtils.Convert(self.Expression, type)), new DynamicMetaObject(AstUtils.Constant(memInfo.Name), BindingRestrictions.Empty, memInfo.Name), target.Clone(tmp) ); var call = Ast.Block(Ast.Assign(tmp, target.Expression), callMo.Expression); if (setMem.ReturnType == typeof(bool)) { memInfo.Body.AddCondition( call, tmp ); } else { memInfo.Body.FinishCondition(Ast.Block(call, AstUtils.Convert(tmp, typeof(object)))); } return setMem.ReturnType != typeof(bool); } } return false; }
private static Expression MakeGenericPropertyExpression(SetOrDeleteMemberInfo memInfo) { return Ast.New( typeof(MemberAccessException).GetConstructor(new Type[] { typeof(string) }), AstUtils.Constant(memInfo.Name) ); }
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) { // TODO (tomat): this used to use setter.ReflectedType, is it still correct? setter = CompilerHelpers.TryGetCallableMethod(targetType, setter); if (!PrivateBinding && !CompilerHelpers.IsVisible(setter)) { setter = null; } } if (setter != null) { if (info.IsStatic != (instance == null)) { memInfo.Body.FinishError( errorSuggestion ?? MakeError( MakeStaticPropertyInstanceAccessError( info, true, instance, target ), typeof(object) ) ); } else if (info.IsStatic && info.DeclaringType != targetType) { memInfo.Body.FinishError( 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.FinishError( errorSuggestion ?? MakeError( MakeMissingMemberErrorForAssignReadOnlyProperty(targetType, instance, memInfo.Name), typeof(object) ) ); } }
private void MakeFieldRule(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type targetType, MemberGroup fields, DynamicMetaObject errorSuggestion) { FieldTracker field = (FieldTracker)fields[0]; // TODO: Tmp variable for target if (instance != null && field.DeclaringType.IsGenericType() && field.DeclaringType.GetGenericTypeDefinition() == typeof(StrongBox <>)) { // work around a CLR bug where we can't access generic fields from dynamic methods. Type[] generic = field.DeclaringType.GetGenericArguments(); memInfo.Body.FinishCondition( MakeReturnValue( Ast.Assign( Ast.Field( AstUtils.Convert(instance.Expression, field.DeclaringType), field.DeclaringType.GetDeclaredField("Value") ), AstUtils.Convert(target.Expression, generic[0]) ), target ) ); } else if (field.IsInitOnly || field.IsLiteral) { memInfo.Body.FinishError( errorSuggestion ?? MakeError( MakeReadOnlyMemberError(targetType, memInfo.Name), typeof(object) ) ); } else if (field.IsStatic && targetType != field.DeclaringType) { memInfo.Body.FinishError( errorSuggestion ?? MakeError( MakeStaticAssignFromDerivedTypeError(targetType, instance, field, target, memInfo.ResolutionFactory), typeof(object) ) ); } else if (field.DeclaringType.IsValueType() && !field.IsStatic) { memInfo.Body.FinishError( errorSuggestion ?? MakeError( MakeSetValueTypeFieldError(field, instance, target), typeof(object) ) ); } else if (field.IsPublic && field.DeclaringType.IsVisible()) { if (!field.IsStatic && instance == null) { memInfo.Body.FinishError( Ast.Throw( Ast.New( typeof(ArgumentException).GetConstructor(new[] { typeof(string) }), AstUtils.Constant("assignment to instance field w/o instance") ), typeof(object) ) ); } else { memInfo.Body.FinishCondition( MakeReturnValue( Ast.Assign( Ast.Field( field.IsStatic ? null : AstUtils.Convert(instance.Expression, field.DeclaringType), field.Field ), ConvertExpression(target.Expression, field.FieldType, ConversionResultKind.ExplicitCast, memInfo.ResolutionFactory) ), target ) ); } } else { Debug.Assert(field.IsStatic || instance != null); memInfo.Body.FinishCondition( MakeReturnValue( Ast.Call( AstUtils.Convert(AstUtils.Constant(field.Field), typeof(FieldInfo)), typeof(FieldInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object) }), field.IsStatic ? AstUtils.Constant(null) : (Expression)AstUtils.Convert(instance.Expression, typeof(object)), AstUtils.Convert(target.Expression, typeof(object)) ), target ) ); } }