2009-07-11 Michael Barker <mike@middlesoft.co.uk>
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / ElementInit.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Microsoft Public License. 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  Microsoft Public License, 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 Microsoft Public License.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 #if CODEPLEX_40
17 using System;
18 #else
19 using System; using Microsoft;
20 #endif
21 using System.Collections.Generic;
22 using System.Collections.ObjectModel;
23 using System.Reflection;
24 using System.Text;
25 #if CODEPLEX_40
26 using System.Dynamic.Utils;
27 #else
28 using Microsoft.Scripting.Utils;
29 #endif
30
31 #if CODEPLEX_40
32 namespace System.Linq.Expressions {
33 #else
34 namespace Microsoft.Linq.Expressions {
35 #endif
36     /// <summary>
37     /// Represents the initialization of a list.
38     /// </summary>
39     public sealed class ElementInit : IArgumentProvider {
40         private MethodInfo _addMethod;
41         private ReadOnlyCollection<Expression> _arguments;
42
43         internal ElementInit(MethodInfo addMethod, ReadOnlyCollection<Expression> arguments) {
44             _addMethod = addMethod;
45             _arguments = arguments;
46         }
47         /// <summary>
48         /// Gets the <see cref="MethodInfo"/> used to add elements to the object.
49         /// </summary>
50         public MethodInfo AddMethod {
51             get { return _addMethod; }
52         }
53
54         /// <summary>
55         /// Gets the list of elements to be added to the object.
56         /// </summary>
57         public ReadOnlyCollection<Expression> Arguments {
58             get { return _arguments; }
59         }
60
61         Expression IArgumentProvider.GetArgument(int index) {
62             return _arguments[index];
63         }
64
65         int IArgumentProvider.ArgumentCount {
66             get {
67                 return _arguments.Count;
68             }
69         }
70
71         /// <summary>
72         /// Creates a <see cref="String"/> representation of the node.
73         /// </summary>
74         /// <returns>A <see cref="String"/> representation of the node.</returns>
75         public override string ToString() {
76             return ExpressionStringBuilder.ElementInitBindingToString(this);
77         }
78     }
79
80
81     public partial class Expression {
82         /// <summary>
83         /// Creates an <see cref="Microsoft.Linq.Expressions.ElementInit">ElementInit</see> expression that represents the initialization of a list.
84         /// </summary>
85         /// <param name="addMethod">The <see cref="MethodInfo"/> for the list's Add method.</param>
86         /// <param name="arguments">An array containing the Expressions to be used to initialize the list.</param>
87         /// <returns>The created <see cref="Microsoft.Linq.Expressions.ElementInit">ElementInit</see> expression.</returns>
88         public static ElementInit ElementInit(MethodInfo addMethod, params Expression[] arguments) {
89             return ElementInit(addMethod, arguments as IEnumerable<Expression>);
90         }
91
92         /// <summary>
93         /// Creates an <see cref="Microsoft.Linq.Expressions.ElementInit">ElementInit</see> expression that represents the initialization of a list.
94         /// </summary>
95         /// <param name="addMethod">The <see cref="MethodInfo"/> for the list's Add method.</param>
96         /// <param name="arguments">An <see cref="IEnumerable{T}"/> containing <see cref="Expression"/> elements to initialize the list.</param>
97         /// <returns>The created <see cref="Microsoft.Linq.Expressions.ElementInit">ElementInit</see> expression.</returns>
98         public static ElementInit ElementInit(MethodInfo addMethod, IEnumerable<Expression> arguments) {
99             ContractUtils.RequiresNotNull(addMethod, "addMethod");
100             ContractUtils.RequiresNotNull(arguments, "arguments");
101
102             var argumentsRO = arguments.ToReadOnly();
103
104             RequiresCanRead(argumentsRO, "arguments");
105             ValidateElementInitAddMethodInfo(addMethod);
106             ValidateArgumentTypes(addMethod, ExpressionType.Call, ref argumentsRO);
107             return new ElementInit(addMethod, argumentsRO);
108         }
109
110         private static void ValidateElementInitAddMethodInfo(MethodInfo addMethod) {
111             ValidateMethodInfo(addMethod);
112             ParameterInfo[] pis = addMethod.GetParametersCached();
113             if (pis.Length == 0) {
114                 throw Error.ElementInitializerMethodWithZeroArgs();
115             }
116             if (!addMethod.Name.Equals("Add", StringComparison.OrdinalIgnoreCase)) {
117                 throw Error.ElementInitializerMethodNotAdd();
118             }
119             if (addMethod.IsStatic) {
120                 throw Error.ElementInitializerMethodStatic();
121             }
122             foreach (ParameterInfo pi in pis) {
123                 if (pi.ParameterType.IsByRef) {
124                     throw Error.ElementInitializerMethodNoRefOutParam(pi.Name, addMethod.Name);
125                 }
126             }
127         }
128     }
129 }