Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / MemberMemberBinding.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.Collections.Generic;
18 using System.Collections.ObjectModel;
19 using System.Dynamic.Utils;
20 using System.Reflection;
21
22 #if !FEATURE_CORE_DLR
23 namespace Microsoft.Scripting.Ast {
24 #else
25 namespace System.Linq.Expressions {
26 #endif
27     /// <summary>
28     /// Represents initializing members of a member of a newly created object.
29     /// </summary>
30     /// <remarks>
31     /// Use the <see cref="M:MemberBind"/> factory methods to create a <see cref="MemberMemberBinding"/>.
32     /// The value of the <see cref="P:MemberBinding.BindingType"/> property of a <see cref="MemberMemberBinding"/> object is <see cref="MemberBinding"/>. 
33     /// </remarks>
34     public sealed class MemberMemberBinding : MemberBinding {
35         ReadOnlyCollection<MemberBinding> _bindings;
36         internal MemberMemberBinding(MemberInfo member, ReadOnlyCollection<MemberBinding> bindings)
37 #pragma warning disable 618
38             : base(MemberBindingType.MemberBinding, member) {
39 #pragma warning restore 618
40             _bindings = bindings;
41         }
42
43         /// <summary>
44         /// Gets the bindings that describe how to initialize the members of a member. 
45         /// </summary>
46         public ReadOnlyCollection<MemberBinding> Bindings {
47             get { return _bindings; }
48         }
49
50         /// <summary>
51         /// Creates a new expression that is like this one, but using the
52         /// supplied children. If all of the children are the same, it will
53         /// return this expression.
54         /// </summary>
55         /// <param name="bindings">The <see cref="Bindings" /> property of the result.</param>
56         /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
57         public MemberMemberBinding Update(IEnumerable<MemberBinding> bindings) {
58             if (bindings == Bindings) {
59                 return this;
60             }
61             return Expression.MemberBind(Member, bindings);
62         }
63     }
64     
65
66     public partial class Expression {
67         /// <summary>
68         /// Creates a <see cref="MemberMemberBinding"/> that represents the recursive initialization of members of a field or property. 
69         /// </summary>
70         /// <param name="member">The <see cref="MemberInfo"/> to set the <see cref="P:MemberBinding.Member"/> property equal to.</param>
71         /// <param name="bindings">An array of <see cref="MemberBinding"/> objects to use to populate the <see cref="P:MemberMemberBindings.Bindings"/> collection.</param>
72         /// <returns>A <see cref="MemberMemberBinding"/> that has the <see cref="P:MemberBinding.BindingType"/> property equal to <see cref="MemberBinding"/> and the <see cref="P:MemberBinding.Member"/> and <see cref="P:MemberMemberBindings.Bindings"/> properties set to the specified values.</returns>
73         public static MemberMemberBinding MemberBind(MemberInfo member, params MemberBinding[] bindings) {
74             ContractUtils.RequiresNotNull(member, "member");
75             ContractUtils.RequiresNotNull(bindings, "bindings");
76             return MemberBind(member, (IEnumerable<MemberBinding>)bindings);
77         }
78         
79         /// <summary>
80         /// Creates a <see cref="MemberMemberBinding"/> that represents the recursive initialization of members of a field or property. 
81         /// </summary>
82         /// <param name="member">The <see cref="MemberInfo"/> to set the <see cref="P:MemberBinding.Member"/> property equal to.</param>
83         /// <param name="bindings">An <see cref="IEnumerable{T}"/> that contains <see cref="MemberBinding"/> objects to use to populate the <see cref="P:MemberMemberBindings.Bindings"/> collection.</param>
84         /// <returns>A <see cref="MemberMemberBinding"/> that has the <see cref="P:MemberBinding.BindingType"/> property equal to <see cref="MemberBinding"/> and the <see cref="P:MemberBinding.Member"/> and <see cref="P:MemberMemberBindings.Bindings"/> properties set to the specified values.</returns>
85         public static MemberMemberBinding MemberBind(MemberInfo member, IEnumerable<MemberBinding> bindings) {
86             ContractUtils.RequiresNotNull(member, "member");
87             ContractUtils.RequiresNotNull(bindings, "bindings");
88             ReadOnlyCollection<MemberBinding> roBindings = bindings.ToReadOnly();
89             Type memberType;
90             ValidateGettableFieldOrPropertyMember(member, out memberType);
91             ValidateMemberInitArgs(memberType, roBindings);
92             return new MemberMemberBinding(member, roBindings);
93         }
94
95         /// <summary>
96         /// Creates a <see cref="MemberMemberBinding"/> that represents the recursive initialization of members of a member that is accessed by using a property accessor method.  
97         /// </summary>
98         /// <param name="propertyAccessor">The <see cref="MemberInfo"/> that represents a property accessor method.</param>
99         /// <param name="bindings">An <see cref="IEnumerable{T}"/> that contains <see cref="MemberBinding"/> objects to use to populate the <see cref="P:MemberMemberBindings.Bindings"/> collection.</param>
100         /// <returns>
101         /// A <see cref="MemberMemberBinding"/> that has the <see cref="P:MemberBinding.BindingType"/> property equal to <see cref="MemberBinding"/>, 
102         /// the Member property set to the <see cref="PropertyInfo"/> that represents the property accessed in <paramref name="propertyAccessor"/>, 
103         /// and <see cref="P:MemberMemberBindings.Bindings"/> properties set to the specified values.
104         /// </returns>
105         public static MemberMemberBinding MemberBind(MethodInfo propertyAccessor, params MemberBinding[] bindings) {
106             ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
107             return MemberBind(GetProperty(propertyAccessor), bindings);
108         }
109
110         /// <summary>
111         /// Creates a <see cref="MemberMemberBinding"/> that represents the recursive initialization of members of a member that is accessed by using a property accessor method.  
112         /// </summary>
113         /// <param name="propertyAccessor">The <see cref="MemberInfo"/> that represents a property accessor method.</param>
114         /// <param name="bindings">An <see cref="IEnumerable{T}"/> that contains <see cref="MemberBinding"/> objects to use to populate the <see cref="P:MemberMemberBindings.Bindings"/> collection.</param>
115         /// <returns>
116         /// A <see cref="MemberMemberBinding"/> that has the <see cref="P:MemberBinding.BindingType"/> property equal to <see cref="MemberBinding"/>, 
117         /// the Member property set to the <see cref="PropertyInfo"/> that represents the property accessed in <paramref name="propertyAccessor"/>, 
118         /// and <see cref="P:MemberMemberBindings.Bindings"/> properties set to the specified values.
119         /// </returns>
120         public static MemberMemberBinding MemberBind(MethodInfo propertyAccessor, IEnumerable<MemberBinding> bindings) {
121             ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
122             return MemberBind(GetProperty(propertyAccessor), bindings);
123         }
124
125         private static void ValidateGettableFieldOrPropertyMember(MemberInfo member, out Type memberType) {
126             FieldInfo fi = member as FieldInfo;
127             if (fi == null) {
128                 PropertyInfo pi = member as PropertyInfo;
129                 if (pi == null) {
130                     throw Error.ArgumentMustBeFieldInfoOrPropertInfo();
131                 }
132                 if (!pi.CanRead) {
133                     throw Error.PropertyDoesNotHaveGetter(pi);
134                 }
135                 memberType = pi.PropertyType;
136             } else {
137                 memberType = fi.FieldType;
138             }
139         }
140         
141         private static void ValidateMemberInitArgs(Type type, ReadOnlyCollection<MemberBinding> bindings) {
142             for (int i = 0, n = bindings.Count; i < n; i++) {
143                 MemberBinding b = bindings[i];
144                 ContractUtils.RequiresNotNull(b, "bindings");
145                 if (!b.Member.DeclaringType.IsAssignableFrom(type)) {
146                     throw Error.NotAMemberOfType(b.Member.Name, type);
147                 }
148             }
149         }
150     }
151 }