BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[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 SILVERLIGHT
21 using System.Core;
22 #endif
23
24 #if CLR2
25 namespace Microsoft.Scripting.Ast {
26 #else
27 namespace System.Linq.Expressions {
28 #endif
29     /// <summary>
30     /// Represents assignment to a member of an object.
31     /// </summary>
32     public sealed class MemberAssignment : MemberBinding {
33         Expression _expression;
34         internal MemberAssignment(MemberInfo member, Expression expression)
35 #pragma warning disable 618
36             : base(MemberBindingType.Assignment, member) {
37 #pragma warning restore 618
38             _expression = expression;
39         }
40         /// <summary>
41         /// Gets the <see cref="Expression"/> which represents the object whose member is being assigned to.
42         /// </summary>
43         public Expression Expression {
44             get { return _expression; }
45         }
46
47         /// <summary>
48         /// Creates a new expression that is like this one, but using the
49         /// supplied children. If all of the children are the same, it will
50         /// return this expression.
51         /// </summary>
52         /// <param name="expression">The <see cref="Expression" /> property of the result.</param>
53         /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
54         public MemberAssignment Update(Expression expression) {
55             if (expression == Expression) {
56                 return this;
57             }
58             return Expression.Bind(Member, expression);
59         }
60     }
61
62
63     public partial class Expression {
64         /// <summary>
65         /// Creates a <see cref="MemberAssignment"/> binding the specified value to the given member.
66         /// </summary>
67         /// <param name="member">The <see cref="MemberInfo"/> for the member which is being assigned to.</param>
68         /// <param name="expression">The value to be assigned to <paramref name="member"/>.</param>
69         /// <returns>The created <see cref="MemberAssignment"/>.</returns>
70         public static MemberAssignment Bind(MemberInfo member, Expression expression) {
71             ContractUtils.RequiresNotNull(member, "member");
72             RequiresCanRead(expression, "expression");
73             Type memberType;
74             ValidateSettableFieldOrPropertyMember(member, out memberType);
75             if (!memberType.IsAssignableFrom(expression.Type)) {
76                 throw Error.ArgumentTypesMustMatch();
77             }
78             return new MemberAssignment(member, expression);
79         }
80
81         /// <summary>
82         /// Creates a <see cref="MemberAssignment"/> binding the specified value to the given property.
83         /// </summary>
84         /// <param name="propertyAccessor">The <see cref="PropertyInfo"/> for the property which is being assigned to.</param>
85         /// <param name="expression">The value to be assigned to <paramref name="propertyAccessor"/>.</param>
86         /// <returns>The created <see cref="MemberAssignment"/>.</returns>
87         public static MemberAssignment Bind(MethodInfo propertyAccessor, Expression expression) {
88             ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
89             ContractUtils.RequiresNotNull(expression, "expression");
90             ValidateMethodInfo(propertyAccessor);
91             return Bind(GetProperty(propertyAccessor), expression);
92         }
93         
94
95         private static void ValidateSettableFieldOrPropertyMember(MemberInfo member, out Type memberType) {
96             FieldInfo fi = member as FieldInfo;
97             if (fi == null) {
98                 PropertyInfo pi = member as PropertyInfo;
99                 if (pi == null) {
100                     throw Error.ArgumentMustBeFieldInfoOrPropertInfo();
101                 }
102                 if (!pi.CanWrite) {
103                     throw Error.PropertyDoesNotHaveSetter(pi);
104                 }
105                 memberType = pi.PropertyType;
106             } else {
107                 memberType = fi.FieldType;
108             }
109         }
110     }
111 }