NewExpression.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Ast / NewExpression.cs / 1305376 / NewExpression.cs

                            /* **************************************************************************** 
 *
 * Copyright (c) Microsoft Corporation.
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/ 

using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Diagnostics;
using System.Dynamic.Utils; 
using System.Reflection;
using System.Runtime.CompilerServices;

#if SILVERLIGHT 
using System.Core;
#endif 
 
namespace System.Linq.Expressions {
 
    /// 
    /// Represents a constructor call.
    /// 
#if !SILVERLIGHT 
    [DebuggerTypeProxy(typeof(Expression.NewExpressionProxy))]
#endif 
    public class NewExpression : Expression, IArgumentProvider { 
        private readonly ConstructorInfo _constructor;
        private IList _arguments; 
        private readonly ReadOnlyCollection _members;

        internal NewExpression(ConstructorInfo constructor, IList arguments, ReadOnlyCollection members) {
            _constructor = constructor; 
            _arguments = arguments;
            _members = members; 
        } 

        ///  
        /// Gets the static type of the expression that this  represents. (Inherited from .)
        /// 
        /// The  that represents the static type of the expression.
        public override Type Type { 
            get { return _constructor.DeclaringType; }
        } 
 
        /// 
        /// Returns the node type of this . (Inherited from .) 
        /// 
        /// The  that represents this expression.
        public sealed override ExpressionType NodeType {
            get { return ExpressionType.New; } 
        }
 
        ///  
        /// Gets the called constructor.
        ///  
        public ConstructorInfo Constructor {
            get { return _constructor; }
        }
 
        /// 
        /// Gets the arguments to the constructor. 
        ///  
        public ReadOnlyCollection Arguments {
            get { return ReturnReadOnly(ref _arguments); } 
        }

        Expression IArgumentProvider.GetArgument(int index) {
            return _arguments[index]; 
        }
 
        int IArgumentProvider.ArgumentCount { 
            get {
                return _arguments.Count; 
            }
        }

        ///  
        /// Gets the members that can retrieve the values of the fields that were initialized with constructor arguments.
        ///  
        public ReadOnlyCollection Members { 
            get { return _members; }
        } 

        /// 
        /// Dispatches to the specific visit method for this node type.
        ///  
        protected internal override Expression Accept(ExpressionVisitor visitor) {
            return visitor.VisitNew(this); 
        } 

        ///  
        /// Creates a new expression that is like this one, but using the
        /// supplied children. If all of the children are the same, it will
        /// return this expression.
        ///  
        /// The  property of the result.
        /// This expression if no children changed, or an expression with the updated children. 
        public NewExpression Update(IEnumerable arguments) { 
            if (arguments == Arguments) {
                return this; 
            }
            if (Members != null) {
                return Expression.New(Constructor, arguments, Members);
            } 
            return Expression.New(Constructor, arguments);
        } 
    } 

    internal class NewValueTypeExpression : NewExpression { 
        private readonly Type _valueType;

        internal NewValueTypeExpression(Type type, ReadOnlyCollection arguments, ReadOnlyCollection members)
            : base(null, arguments, members) { 
            _valueType = type;
        } 
 
        public sealed override Type Type {
            get { return _valueType; } 
        }
    }

    public partial class Expression { 

        ///  
        /// Creates a new  that represents calling the specified constructor that takes no arguments. 
        /// 
        /// The  to set the  property equal to. 
        /// A  that has the  property equal to  and the  property set to the specified value.
        public static NewExpression New(ConstructorInfo constructor) {
            return New(constructor, (IEnumerable)null);
        } 

 
        ///  
        /// Creates a new  that represents calling the specified constructor that takes no arguments.
        ///  
        /// The  to set the  property equal to.
        /// An array of  objects to use to populate the Arguments collection.
        /// A  that has the  property equal to  and the  and  properties set to the specified value.
        public static NewExpression New(ConstructorInfo constructor, params Expression[] arguments) { 
            return New(constructor, (IEnumerable)arguments);
        } 
 

        ///  
        /// Creates a new  that represents calling the specified constructor that takes no arguments.
        /// 
        /// The  to set the  property equal to.
        /// An  of  objects to use to populate the Arguments collection. 
        /// A  that has the  property equal to  and the  and  properties set to the specified value.
        public static NewExpression New(ConstructorInfo constructor, IEnumerable arguments) { 
            ContractUtils.RequiresNotNull(constructor, "constructor"); 
            ContractUtils.RequiresNotNull(constructor.DeclaringType, "constructor.DeclaringType");
            TypeUtils.ValidateType(constructor.DeclaringType); 
            var argList = arguments.ToReadOnly();
            ValidateArgumentTypes(constructor, ExpressionType.New, ref argList);

            return new NewExpression(constructor, argList, null); 
        }
 
 
        /// 
        /// Creates a new  that represents calling the specified constructor with the specified arguments. The members that access the constructor initialized fields are specified. 
        /// 
        /// The  to set the  property equal to.
        /// An  of  objects to use to populate the Arguments collection.
        /// An  of  objects to use to populate the Members collection. 
        /// A  that has the  property equal to  and the ,  and  properties set to the specified value.
        public static NewExpression New(ConstructorInfo constructor, IEnumerable arguments, IEnumerable members) { 
            ContractUtils.RequiresNotNull(constructor, "constructor"); 
            var memberList = members.ToReadOnly();
            var argList = arguments.ToReadOnly(); 
            ValidateNewArgs(constructor, ref argList, ref memberList);
            return new NewExpression(constructor, argList, memberList);
        }
 

        ///  
        /// Creates a new  that represents calling the specified constructor with the specified arguments. The members that access the constructor initialized fields are specified. 
        /// 
        /// The  to set the  property equal to. 
        /// An  of  objects to use to populate the Arguments collection.
        /// An Array of  objects to use to populate the Members collection.
        /// A  that has the  property equal to  and the ,  and  properties set to the specified value.
        public static NewExpression New(ConstructorInfo constructor, IEnumerable arguments, params MemberInfo[] members) { 
            return New(constructor, arguments, (IEnumerable)members);
        } 
 

        ///  
        /// Creates a  that represents calling the parameterless constructor of the specified type.
        /// 
        /// A  that has a constructor that takes no arguments. 
        /// A  that has the  property equal to New and the Constructor property set to the ConstructorInfo that represents the parameterless constructor of the specified type. 
        public static NewExpression New(Type type) {
            ContractUtils.RequiresNotNull(type, "type"); 
            if (type == typeof(void)) { 
                throw Error.ArgumentCannotBeOfTypeVoid();
            } 
            ConstructorInfo ci = null;
            if (!type.IsValueType) {
                ci = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, System.Type.EmptyTypes, null);
                if (ci == null) { 
                    throw Error.TypeMissingDefaultConstructor(type);
                } 
                return New(ci); 
            }
            return new NewValueTypeExpression(type, EmptyReadOnlyCollection.Instance, null); 
        }


 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
        private static void ValidateNewArgs(ConstructorInfo constructor, ref ReadOnlyCollection arguments, ref ReadOnlyCollection members) { 
            ParameterInfo[] pis; 
            if ((pis = constructor.GetParametersCached()).Length > 0) {
                if (arguments.Count != pis.Length) { 
                    throw Error.IncorrectNumberOfConstructorArguments();
                }
                if (arguments.Count != members.Count) {
                    throw Error.IncorrectNumberOfArgumentsForMembers(); 
                }
                Expression[] newArguments = null; 
                MemberInfo[] newMembers = null; 
                for (int i = 0, n = arguments.Count; i < n; i++) {
                    Expression arg = arguments[i]; 
                    RequiresCanRead(arg, "argument");
                    MemberInfo member = members[i];
                    ContractUtils.RequiresNotNull(member, "member");
                    if (!TypeUtils.AreEquivalent(member.DeclaringType, constructor.DeclaringType)) { 
                        throw Error.ArgumentMemberNotDeclOnType(member.Name, constructor.DeclaringType.Name);
                    } 
                    Type memberType; 
                    ValidateAnonymousTypeMember(ref member, out memberType);
                    if (!TypeUtils.AreReferenceAssignable(memberType, arg.Type)) { 
                        if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), memberType) && memberType.IsAssignableFrom(arg.GetType())) {
                            arg = Expression.Quote(arg);
                        } else {
                            throw Error.ArgumentTypeDoesNotMatchMember(arg.Type, memberType); 
                        }
                    } 
                    ParameterInfo pi = pis[i]; 
                    Type pType = pi.ParameterType;
                    if (pType.IsByRef) { 
                        pType = pType.GetElementType();
                    }
                    if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) {
                        if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.Type)) { 
                            arg = Expression.Quote(arg);
                        } else { 
                            throw Error.ExpressionTypeDoesNotMatchConstructorParameter(arg.Type, pType); 
                        }
                    } 
                    if (newArguments == null && arg != arguments[i]) {
                        newArguments = new Expression[arguments.Count];
                        for (int j = 0; j < i; j++) {
                            newArguments[j] = arguments[j]; 
                        }
                    } 
                    if (newArguments != null) { 
                        newArguments[i] = arg;
                    } 

                    if (newMembers == null && member != members[i]) {
                        newMembers = new MemberInfo[members.Count];
                        for (int j = 0; j < i; j++) { 
                            newMembers[j] = members[j];
                        } 
                    } 
                    if (newMembers != null) {
                        newMembers[i] = member; 
                    }
                }
                if (newArguments != null) {
                    arguments = new TrueReadOnlyCollection(newArguments); 
                }
                if (newMembers != null) { 
                    members = new TrueReadOnlyCollection(newMembers); 
                }
            } else if (arguments != null && arguments.Count > 0) { 
                throw Error.IncorrectNumberOfConstructorArguments();
            } else if (members != null && members.Count > 0) {
                throw Error.IncorrectNumberOfMembersForGivenConstructor();
            } 
        }
 
 
        private static void ValidateAnonymousTypeMember(ref MemberInfo member, out Type memberType) {
            switch (member.MemberType) { 
                case MemberTypes.Field:
                    FieldInfo field = member as FieldInfo;
                    if (field.IsStatic) {
                        throw Error.ArgumentMustBeInstanceMember(); 
                    }
                    memberType = field.FieldType; 
                    break; 
                case MemberTypes.Property:
                    PropertyInfo pi = member as PropertyInfo; 
                    if (!pi.CanRead) {
                        throw Error.PropertyDoesNotHaveGetter(pi);
                    }
                    if (pi.GetGetMethod().IsStatic) { 
                        throw Error.ArgumentMustBeInstanceMember();
                    } 
                    memberType = pi.PropertyType; 
                    break;
                case MemberTypes.Method: 
                    MethodInfo method = member as MethodInfo;
                    if (method.IsStatic) {
                        throw Error.ArgumentMustBeInstanceMember();
                    } 

                    PropertyInfo prop = GetProperty(method); 
                    member = prop; 
                    memberType = prop.PropertyType;
                    break; 
                default:
                    throw Error.ArgumentMustBeFieldInfoOrPropertInfoOrMethod();
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK