Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / MemberListBinding.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;
18 using System.Collections.Generic;
19 using System.Collections.ObjectModel;
20 using System.Dynamic.Utils;
21 using System.Reflection;
22
23 #if !FEATURE_CORE_DLR
24 namespace Microsoft.Scripting.Ast {
25 #else
26 namespace System.Linq.Expressions {
27 #endif
28
29     /// <summary>
30     /// Represents initializing the elements of a collection member of a newly created object. 
31     /// </summary>
32     public sealed class MemberListBinding : MemberBinding {
33         ReadOnlyCollection<ElementInit> _initializers;
34         internal MemberListBinding(MemberInfo member, ReadOnlyCollection<ElementInit> initializers)
35 #pragma warning disable 618
36             : base(MemberBindingType.ListBinding, member) {
37 #pragma warning restore 618
38             _initializers = initializers;
39         }
40
41         /// <summary>
42         /// Gets the element initializers for initializing a collection member of a newly created object.
43         /// </summary>
44         public ReadOnlyCollection<ElementInit> Initializers {
45             get { return _initializers; }
46         }
47
48         /// <summary>
49         /// Creates a new expression that is like this one, but using the
50         /// supplied children. If all of the children are the same, it will
51         /// return this expression.
52         /// </summary>
53         /// <param name="initializers">The <see cref="Initializers" /> property of the result.</param>
54         /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
55         public MemberListBinding Update(IEnumerable<ElementInit> initializers) {
56             if (initializers == Initializers) {
57                 return this;
58             }
59             return Expression.ListBind(Member, initializers);
60         }
61     }
62     
63
64     public partial class Expression {
65
66         ///<summary>Creates a <see cref="T:System.Linq.Expressions.MemberListBinding" /> where the member is a field or property.</summary>
67         ///<returns>A <see cref="T:System.Linq.Expressions.MemberListBinding" /> that has the <see cref="P:System.Linq.Expressions.MemberBinding.BindingType" /> property equal to <see cref="F:System.Linq.Expressions.MemberBindingType.ListBinding" /> and the <see cref="P:System.Linq.Expressions.MemberBinding.Member" /> and <see cref="P:System.Linq.Expressions.MemberListBinding.Initializers" /> properties set to the specified values.</returns>
68         ///<param name="member">A <see cref="T:System.Reflection.MemberInfo" /> that represents a field or property to set the <see cref="P:System.Linq.Expressions.MemberBinding.Member" /> property equal to.</param>
69         ///<param name="initializers">An array of <see cref="T:System.Linq.Expressions.ElementInit" /> objects to use to populate the <see cref="P:System.Linq.Expressions.MemberListBinding.Initializers" /> collection.</param>
70         ///<exception cref="T:System.ArgumentNullException">
71         ///<paramref name="member" /> is null. -or-One or more elements of <paramref name="initializers" /> is null.</exception>
72         ///<exception cref="T:System.ArgumentException">
73         ///<paramref name="member" /> does not represent a field or property.-or-The <see cref="P:System.Reflection.FieldInfo.FieldType" /> or <see cref="P:System.Reflection.PropertyInfo.PropertyType" /> of the field or property that <paramref name="member" /> represents does not implement <see cref="T:System.Collections.IEnumerable" />.</exception>
74         public static MemberListBinding ListBind(MemberInfo member, params ElementInit[] initializers) {
75             ContractUtils.RequiresNotNull(member, "member");
76             ContractUtils.RequiresNotNull(initializers, "initializers");
77             return ListBind(member, (IEnumerable<ElementInit>)initializers);
78         }
79
80         ///<summary>Creates a <see cref="T:System.Linq.Expressions.MemberListBinding" /> where the member is a field or property.</summary>
81         ///<returns>A <see cref="T:System.Linq.Expressions.MemberListBinding" /> that has the <see cref="P:System.Linq.Expressions.MemberBinding.BindingType" /> property equal to <see cref="F:System.Linq.Expressions.MemberBindingType.ListBinding" /> and the <see cref="P:System.Linq.Expressions.MemberBinding.Member" /> and <see cref="P:System.Linq.Expressions.MemberListBinding.Initializers" /> properties set to the specified values.</returns>
82         ///<param name="member">A <see cref="T:System.Reflection.MemberInfo" /> that represents a field or property to set the <see cref="P:System.Linq.Expressions.MemberBinding.Member" /> property equal to.</param>
83         ///<param name="initializers">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:System.Linq.Expressions.ElementInit" /> objects to use to populate the <see cref="P:System.Linq.Expressions.MemberListBinding.Initializers" /> collection.</param>
84         ///<exception cref="T:System.ArgumentNullException">
85         ///<paramref name="member" /> is null. -or-One or more elements of <paramref name="initializers" /> is null.</exception>
86         ///<exception cref="T:System.ArgumentException">
87         ///<paramref name="member" /> does not represent a field or property.-or-The <see cref="P:System.Reflection.FieldInfo.FieldType" /> or <see cref="P:System.Reflection.PropertyInfo.PropertyType" /> of the field or property that <paramref name="member" /> represents does not implement <see cref="T:System.Collections.IEnumerable" />.</exception>
88         public static MemberListBinding ListBind(MemberInfo member, IEnumerable<ElementInit> initializers) {
89             ContractUtils.RequiresNotNull(member, "member");
90             ContractUtils.RequiresNotNull(initializers, "initializers");
91             Type memberType;
92             ValidateGettableFieldOrPropertyMember(member, out memberType);
93             var initList = initializers.ToReadOnly();
94             ValidateListInitArgs(memberType, initList);
95             return new MemberListBinding(member, initList);
96         }
97
98         ///<summary>Creates a <see cref="T:System.Linq.Expressions.MemberListBinding" /> object based on a specified property accessor method.</summary>
99         ///<returns>A <see cref="T:System.Linq.Expressions.MemberListBinding" /> that has the <see cref="P:System.Linq.Expressions.MemberBinding.BindingType" /> property equal to <see cref="F:System.Linq.Expressions.MemberBindingType.ListBinding" />, the <see cref="P:System.Linq.Expressions.MemberBinding.Member" /> property set to the <see cref="T:System.Reflection.MemberInfo" /> that represents the property accessed in <paramref name="propertyAccessor" />, and <see cref="P:System.Linq.Expressions.MemberListBinding.Initializers" /> populated with the elements of <paramref name="initializers" />.</returns>
100         ///<param name="propertyAccessor">A <see cref="T:System.Reflection.MethodInfo" /> that represents a property accessor method.</param>
101         ///<param name="initializers">An array of <see cref="T:System.Linq.Expressions.ElementInit" /> objects to use to populate the <see cref="P:System.Linq.Expressions.MemberListBinding.Initializers" /> collection.</param>
102         ///<exception cref="T:System.ArgumentNullException">
103         ///<paramref name="propertyAccessor" /> is null. -or-One or more elements of <paramref name="initializers" /> is null.</exception>
104         ///<exception cref="T:System.ArgumentException">
105         ///<paramref name="propertyAccessor" /> does not represent a property accessor method.-or-The <see cref="P:System.Reflection.PropertyInfo.PropertyType" /> of the property that the method represented by <paramref name="propertyAccessor" /> accesses does not implement <see cref="T:System.Collections.IEnumerable" />.</exception>  
106         public static MemberListBinding ListBind(MethodInfo propertyAccessor, params ElementInit[] initializers) {
107             ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
108             ContractUtils.RequiresNotNull(initializers, "initializers");
109             return ListBind(propertyAccessor, (IEnumerable<ElementInit>)initializers);
110         }
111
112         ///<summary>Creates a <see cref="T:System.Linq.Expressions.MemberListBinding" /> based on a specified property accessor method.</summary>
113         ///<returns>A <see cref="T:System.Linq.Expressions.MemberListBinding" /> that has the <see cref="P:System.Linq.Expressions.MemberBinding.BindingType" /> property equal to <see cref="F:System.Linq.Expressions.MemberBindingType.ListBinding" />, the <see cref="P:System.Linq.Expressions.MemberBinding.Member" /> property set to the <see cref="T:System.Reflection.MemberInfo" /> that represents the property accessed in <paramref name="propertyAccessor" />, and <see cref="P:System.Linq.Expressions.MemberListBinding.Initializers" /> populated with the elements of <paramref name="initializers" />.</returns>
114         ///<param name="propertyAccessor">A <see cref="T:System.Reflection.MethodInfo" /> that represents a property accessor method.</param>
115         ///<param name="initializers">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> that contains <see cref="T:System.Linq.Expressions.ElementInit" /> objects to use to populate the <see cref="P:System.Linq.Expressions.MemberListBinding.Initializers" /> collection.</param>
116         ///<exception cref="T:System.ArgumentNullException">
117         ///<paramref name="propertyAccessor" /> is null. -or-One or more elements of <paramref name="initializers" /> are null.</exception>
118         ///<exception cref="T:System.ArgumentException">
119         ///<paramref name="propertyAccessor" /> does not represent a property accessor method.-or-The <see cref="P:System.Reflection.PropertyInfo.PropertyType" /> of the property that the method represented by <paramref name="propertyAccessor" /> accesses does not implement <see cref="T:System.Collections.IEnumerable" />.</exception>        
120         public static MemberListBinding ListBind(MethodInfo propertyAccessor, IEnumerable<ElementInit> initializers) {
121             ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor");
122             ContractUtils.RequiresNotNull(initializers, "initializers");
123             return ListBind(GetProperty(propertyAccessor), initializers);
124         }
125
126         private static void ValidateListInitArgs(Type listType, ReadOnlyCollection<ElementInit> initializers) {
127             if (!typeof(IEnumerable).IsAssignableFrom(listType)) {
128                 throw Error.TypeNotIEnumerable(listType);
129             }
130             for (int i = 0, n = initializers.Count; i < n; i++) {
131                 ElementInit element = initializers[i];
132                 ContractUtils.RequiresNotNull(element, "initializers");
133                 ValidateCallInstanceType(listType, element.AddMethod);
134             }
135         }
136     }
137 }