Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / MemberAssignment.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Apache License, Version 2.0. 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  Apache License, Version 2.0, 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 Apache License, Version 2.0.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 using System;
17 using System.Dynamic.Utils;
18 using System.Reflection;
19
20 #if !FEATURE_CORE_DLR
21 namespace Microsoft.Scripting.Ast {
22 #else
23 namespace System.Linq.Expressions {
24 #endif
25     /// <summary>
26     /// Represents assignment to a member of an object.
27     /// </summary>
28     public sealed class MemberAssignment : MemberBinding {
29         Expression _expression;
30         internal MemberAssignment(MemberInfo member, Expression expression)
31 #pragma warning disable 618
32             : base(MemberBindingType.Assignment, member) {
33 #pragma warning restore 618
34             _expression = expression;
35         }
36         /// <summary>
37         /// Gets the <see cref="Expression"/> which represents the object whose member is being assigned to.
38         /// </summary>
39         public Expression Expression {
40             get { return _expression; }
41         }
42
43         /// <summary>
44         /// Creates a new expression that is like this one, but using the
45         /// supplied children. If all of the children are the same, it will
46         /// return this expression.
47         /// </summary>
48         /// <param name="expression">The <see cref="Expression" /> property of the result.</param>
49         /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
50         public MemberAssignment Update(Expression expression) {
51             if (expression == Expression) {
52                 return this;
53             }
54             return Expression.Bind(Member, expression);
55         }
56     }
57
58
59     public partial class Expression {
60         /// <summary>
61         /// Creates a <see cref="MemberAssignment"/> binding the specified value to the given member.
62         /// </summary>
63         /// <param name="member">The <see cref="MemberInfo"/> for the member which is being assigned to.</param>
64         /// <param name="expression">The value to be assigned to <paramref name="member"/>.</param>
65         /// <returns>The created <see cref="MemberAssignment"/>.</returns>
66         public static MemberAssignment Bind(MemberInfo member, Expression expression) {
67             ContractUtils.RequiresNotNull(member, "member");
68             RequiresCanRead(expression, "expression");
69             Type memberType;
70             ValidateSettableFieldOrPropertyMember(member, out memberType);
71             if (!memberType.IsAssignableFrom(expression.Type)) {
72                 throw Error.ArgumentTypesMustMatch();
73             }
74             return new MemberAssignment(member, expression);
75         }
76
77         /// <summary>
78         /// Creates a <see cref="MemberAssignment"/> binding the specified value to the given property.
79         /// </summary>
80         /// <param name="propertyAccessor">The <see cref="PropertyInfo"/> for the property which is being assigned to.</param>
81         /// <param name="expression">The value to be assigned to <paramref name="propertyAccessor"/>.</param>
82         /// <returns>The created <see cref="MemberAssignment"/>.</returns>
83         public static MemberAssignment Bind(MethodInfo propertyAccessor, Expression expression) {
84             ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
85             ContractUtils.RequiresNotNull(expression, "expression");
86             ValidateMethodInfo(propertyAccessor);
87             return Bind(GetProperty(propertyAccessor), expression);
88         }
89         
90
91         private static void ValidateSettableFieldOrPropertyMember(MemberInfo member, out Type memberType) {
92             FieldInfo fi = member as FieldInfo;
93             if (fi == null) {
94                 PropertyInfo pi = member as PropertyInfo;
95                 if (pi == null) {
96                     throw Error.ArgumentMustBeFieldInfoOrPropertInfo();
97                 }
98                 if (!pi.CanWrite) {
99                     throw Error.PropertyDoesNotHaveSetter(pi);
100                 }
101                 memberType = pi.PropertyType;
102             } else {
103                 memberType = fi.FieldType;
104             }
105         }
106     }
107 }