DataShape.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DLinq / Dlinq / DataShape.cs / 1 / DataShape.cs

                            using System; 
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Linq; 
using System.Linq.Expressions;
using System.Collections; 
using System.Data.Linq.SqlClient; 
using System.Diagnostics.CodeAnalysis;
 
namespace System.Data.Linq {
    sealed public class DataLoadOptions {
        bool frozen;
        Dictionary includes = new Dictionary(); 
        Dictionary subqueries = new Dictionary();
 
        ///  
        /// Describe a property that is automatically loaded when the containing instance is loaded
        ///  
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "[....]: Generic types are an important part of Linq APIs and they could not exist without nested generic support.")]
        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "[....]: Need to provide static typing.")]
        public void LoadWith(Expression> expression) {
            if (expression == null) { 
                throw Error.ArgumentNull("expression");
            } 
            MemberInfo mi = GetLoadWithMemberInfo(expression); 
            this.Preload(mi);
        } 

        /// 
        /// Describe a property that is automatically loaded when the containing instance is loaded
        ///  
        public void LoadWith(LambdaExpression expression) {
            if (expression == null) { 
                throw Error.ArgumentNull("expression"); 
            }
            MemberInfo mi = GetLoadWithMemberInfo(expression); 
            this.Preload(mi);
        }

        ///  
        /// Place a subquery on the given association.
        ///  
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "[....]: Generic types are an important part of Linq APIs and they could not exist without nested generic support.")] 
        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "[....]: Need to provide static typing.")]
        public void AssociateWith(Expression> expression) { 
            if (expression == null) {
                throw Error.ArgumentNull("expression");
            }
            this.AssociateWithInternal(expression); 
        }
 
        ///  
        /// Place a subquery on the given association.
        ///  
        public void AssociateWith(LambdaExpression expression) {
            if (expression == null) {
                throw Error.ArgumentNull("expression");
            } 
            this.AssociateWithInternal(expression);
        } 
 
        private void AssociateWithInternal(LambdaExpression expression) {
            // Strip the cast-to-object. 
            Expression op = expression.Body;
            while (op.NodeType == ExpressionType.Convert || op.NodeType == ExpressionType.ConvertChecked) {
                op = ((UnaryExpression)op).Operand;
            } 
            LambdaExpression lambda = Expression.Lambda(op, expression.Parameters.ToArray());
            MemberInfo mi = Searcher.MemberInfoOf(lambda); 
            this.Subquery(mi, lambda); 
        }
 
        /// 
        /// Determines if the member is automatically loaded with its containing instances.
        /// 
        /// The member this is automatically loaded. 
        /// True if the member is automatically loaded.
        internal bool IsPreloaded(MemberInfo member) { 
            if (member == null) { 
                throw Error.ArgumentNull("member");
            } 
            return includes.ContainsKey(new MetaPosition(member));
        }

        ///  
        /// Gets the subquery expression associated with the member.
        ///  
        /// The member with the subquery. 
        /// 
        internal LambdaExpression GetAssociationSubquery(MemberInfo member) { 
            if (member == null) {
                throw Error.ArgumentNull("member");
            }
            LambdaExpression expression = null; 
            subqueries.TryGetValue(new MetaPosition(member), out expression);
            return expression; 
        } 

        ///  
        /// Freeze the shape. Any further attempts to modify the shape will result in
        /// an exception.
        /// 
        internal void Freeze() { 
            this.frozen = true;
        } 
 
        /// 
        /// Describe a property that is automatically loaded when the containing instance is loaded 
        /// 
        internal void Preload(MemberInfo association) {
            if (association == null) {
                throw Error.ArgumentNull("association"); 
            }
            if (this.frozen) { 
                throw Error.IncludeNotAllowedAfterFreeze(); 
            }
            this.includes.Add(new MetaPosition(association), association); 
            ValidateTypeGraphAcyclic();
        }

        ///  
        /// Place a subquery on the given association.
        ///  
        private void Subquery(MemberInfo association, LambdaExpression subquery) { 
            if (this.frozen) {
                throw Error.SubqueryNotAllowedAfterFreeze(); 
            }
            subquery = (LambdaExpression)System.Data.Linq.SqlClient.Funcletizer.Funcletize(subquery); // Layering violation.
            ValidateSubqueryMember(association);
            ValidateSubqueryExpression(subquery); 
            this.subqueries[new MetaPosition(association)] = subquery;
        } 
 
        /// 
        /// If the lambda specified is of the form p.A, where p is the parameter 
        /// and A is a member on p, the MemberInfo for A is returned.  If
        /// the expression is not of this form, an exception is thrown.
        /// 
        private static MemberInfo GetLoadWithMemberInfo(LambdaExpression lambda) 
        {
            // When the specified member is a value type, there will be a conversion 
            // to object that we need to strip 
            Expression body = lambda.Body;
            if (body != null && (body.NodeType == ExpressionType.Convert || body.NodeType == ExpressionType.ConvertChecked)) 
            {
                body = ((UnaryExpression)body).Operand;
            }
 
            MemberExpression mex = body as MemberExpression;
            if (mex != null && mex.Expression.NodeType == ExpressionType.Parameter) 
            { 
                return mex.Member;
            } 
            else
            {
                throw Error.InvalidLoadOptionsLoadMemberSpecification();
            } 
        }
 
        private static class Searcher { 
            static internal MemberInfo MemberInfoOf(LambdaExpression lambda) {
                Visitor v = new Visitor(); 
                v.VisitLambda(lambda);
                return v.MemberInfo;
            }
            private class Visitor : System.Data.Linq.SqlClient.ExpressionVisitor { 
                internal MemberInfo MemberInfo;
                internal override Expression VisitMemberAccess(MemberExpression m) { 
                    this.MemberInfo = m.Member; 
                    return base.VisitMemberAccess(m);
                } 

                internal override Expression VisitMethodCall(MethodCallExpression m) {
                    this.Visit(m.Object);
                    foreach (Expression arg in m.Arguments) { 
                        this.Visit(arg);
                        break; // Only follow the extension method 'this' 
                    } 
                    return m;
                } 

            }
        }
 
        private void ValidateTypeGraphAcyclic() {
            IEnumerable edges = this.includes.Values; 
            int removed = 0; 

            for (int loop = 0; loop < this.includes.Count; ++loop) { 
                // Build a list of all edge targets.
                HashSet edgeTargets = new HashSet();
                foreach (MemberInfo edge in edges) {
                    edgeTargets.Add(GetIncludeTarget(edge)); 
                }
                // Remove all edges with sources matching no target. 
                List newEdges = new List(); 
                bool someRemoved = false;
                foreach (MemberInfo edge in edges) { 
                    if (edgeTargets.Where(et=>et.IsAssignableFrom(edge.DeclaringType) || edge.DeclaringType.IsAssignableFrom(et)).Any()) {
                        newEdges.Add(edge);
                    }
                    else { 
                        ++removed;
                        someRemoved = true; 
                        if (removed == this.includes.Count) 
                            return;
                    } 
                }
                if (!someRemoved) {
                    throw Error.IncludeCycleNotAllowed(); // No edges removed, there must be a loop.
                } 
                edges = newEdges;
            } 
            throw new InvalidOperationException("Bug in ValidateTypeGraphAcyclic"); // Getting here means a bug. 
        }
 
        private static Type GetIncludeTarget(MemberInfo mi) {
            Type mt = System.Data.Linq.SqlClient.TypeSystem.GetMemberType(mi);
            if (mt.IsGenericType) {
                return mt.GetGenericArguments()[0]; 
            }
            return mt; 
        } 

        private static void ValidateSubqueryMember(MemberInfo mi) { 
            Type memberType = System.Data.Linq.SqlClient.TypeSystem.GetMemberType(mi);
            if (memberType == null) {
                throw Error.SubqueryNotSupportedOn(mi);
            } 
            if (!typeof(IEnumerable).IsAssignableFrom(memberType)) {
                throw Error.SubqueryNotSupportedOnType(mi.Name, mi.DeclaringType); 
            } 
        }
 
        private static void ValidateSubqueryExpression(LambdaExpression subquery) {
            if (!typeof(IEnumerable).IsAssignableFrom(subquery.Body.Type)) {
                throw Error.SubqueryMustBeSequence();
            } 
            new SubqueryValidator().VisitLambda(subquery);
        } 
 
        /// 
        /// Ensure that the subquery follows the rules for subqueries. 
        /// 
        private class SubqueryValidator : System.Data.Linq.SqlClient.ExpressionVisitor {
            bool isTopLevel = true;
            internal override Expression VisitMethodCall(MethodCallExpression m) { 
                bool was = isTopLevel;
                try { 
                    if (isTopLevel && !SubqueryRules.IsSupportedTopLevelMethod(m.Method)) 
                        throw Error.SubqueryDoesNotSupportOperator(m.Method.Name);
                    isTopLevel = false; 
                    return base.VisitMethodCall(m);
                }
                finally {
                    isTopLevel = was; 
                }
            } 
        } 

        ///  
        /// Whether there have been LoadOptions specified.
        /// 
        internal bool IsEmpty {
            get { return this.includes.Count == 0 && this.subqueries.Count == 0; } 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System; 
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Linq; 
using System.Linq.Expressions;
using System.Collections; 
using System.Data.Linq.SqlClient; 
using System.Diagnostics.CodeAnalysis;
 
namespace System.Data.Linq {
    sealed public class DataLoadOptions {
        bool frozen;
        Dictionary includes = new Dictionary(); 
        Dictionary subqueries = new Dictionary();
 
        ///  
        /// Describe a property that is automatically loaded when the containing instance is loaded
        ///  
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "[....]: Generic types are an important part of Linq APIs and they could not exist without nested generic support.")]
        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "[....]: Need to provide static typing.")]
        public void LoadWith(Expression> expression) {
            if (expression == null) { 
                throw Error.ArgumentNull("expression");
            } 
            MemberInfo mi = GetLoadWithMemberInfo(expression); 
            this.Preload(mi);
        } 

        /// 
        /// Describe a property that is automatically loaded when the containing instance is loaded
        ///  
        public void LoadWith(LambdaExpression expression) {
            if (expression == null) { 
                throw Error.ArgumentNull("expression"); 
            }
            MemberInfo mi = GetLoadWithMemberInfo(expression); 
            this.Preload(mi);
        }

        ///  
        /// Place a subquery on the given association.
        ///  
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "[....]: Generic types are an important part of Linq APIs and they could not exist without nested generic support.")] 
        [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "[....]: Need to provide static typing.")]
        public void AssociateWith(Expression> expression) { 
            if (expression == null) {
                throw Error.ArgumentNull("expression");
            }
            this.AssociateWithInternal(expression); 
        }
 
        ///  
        /// Place a subquery on the given association.
        ///  
        public void AssociateWith(LambdaExpression expression) {
            if (expression == null) {
                throw Error.ArgumentNull("expression");
            } 
            this.AssociateWithInternal(expression);
        } 
 
        private void AssociateWithInternal(LambdaExpression expression) {
            // Strip the cast-to-object. 
            Expression op = expression.Body;
            while (op.NodeType == ExpressionType.Convert || op.NodeType == ExpressionType.ConvertChecked) {
                op = ((UnaryExpression)op).Operand;
            } 
            LambdaExpression lambda = Expression.Lambda(op, expression.Parameters.ToArray());
            MemberInfo mi = Searcher.MemberInfoOf(lambda); 
            this.Subquery(mi, lambda); 
        }
 
        /// 
        /// Determines if the member is automatically loaded with its containing instances.
        /// 
        /// The member this is automatically loaded. 
        /// True if the member is automatically loaded.
        internal bool IsPreloaded(MemberInfo member) { 
            if (member == null) { 
                throw Error.ArgumentNull("member");
            } 
            return includes.ContainsKey(new MetaPosition(member));
        }

        ///  
        /// Gets the subquery expression associated with the member.
        ///  
        /// The member with the subquery. 
        /// 
        internal LambdaExpression GetAssociationSubquery(MemberInfo member) { 
            if (member == null) {
                throw Error.ArgumentNull("member");
            }
            LambdaExpression expression = null; 
            subqueries.TryGetValue(new MetaPosition(member), out expression);
            return expression; 
        } 

        ///  
        /// Freeze the shape. Any further attempts to modify the shape will result in
        /// an exception.
        /// 
        internal void Freeze() { 
            this.frozen = true;
        } 
 
        /// 
        /// Describe a property that is automatically loaded when the containing instance is loaded 
        /// 
        internal void Preload(MemberInfo association) {
            if (association == null) {
                throw Error.ArgumentNull("association"); 
            }
            if (this.frozen) { 
                throw Error.IncludeNotAllowedAfterFreeze(); 
            }
            this.includes.Add(new MetaPosition(association), association); 
            ValidateTypeGraphAcyclic();
        }

        ///  
        /// Place a subquery on the given association.
        ///  
        private void Subquery(MemberInfo association, LambdaExpression subquery) { 
            if (this.frozen) {
                throw Error.SubqueryNotAllowedAfterFreeze(); 
            }
            subquery = (LambdaExpression)System.Data.Linq.SqlClient.Funcletizer.Funcletize(subquery); // Layering violation.
            ValidateSubqueryMember(association);
            ValidateSubqueryExpression(subquery); 
            this.subqueries[new MetaPosition(association)] = subquery;
        } 
 
        /// 
        /// If the lambda specified is of the form p.A, where p is the parameter 
        /// and A is a member on p, the MemberInfo for A is returned.  If
        /// the expression is not of this form, an exception is thrown.
        /// 
        private static MemberInfo GetLoadWithMemberInfo(LambdaExpression lambda) 
        {
            // When the specified member is a value type, there will be a conversion 
            // to object that we need to strip 
            Expression body = lambda.Body;
            if (body != null && (body.NodeType == ExpressionType.Convert || body.NodeType == ExpressionType.ConvertChecked)) 
            {
                body = ((UnaryExpression)body).Operand;
            }
 
            MemberExpression mex = body as MemberExpression;
            if (mex != null && mex.Expression.NodeType == ExpressionType.Parameter) 
            { 
                return mex.Member;
            } 
            else
            {
                throw Error.InvalidLoadOptionsLoadMemberSpecification();
            } 
        }
 
        private static class Searcher { 
            static internal MemberInfo MemberInfoOf(LambdaExpression lambda) {
                Visitor v = new Visitor(); 
                v.VisitLambda(lambda);
                return v.MemberInfo;
            }
            private class Visitor : System.Data.Linq.SqlClient.ExpressionVisitor { 
                internal MemberInfo MemberInfo;
                internal override Expression VisitMemberAccess(MemberExpression m) { 
                    this.MemberInfo = m.Member; 
                    return base.VisitMemberAccess(m);
                } 

                internal override Expression VisitMethodCall(MethodCallExpression m) {
                    this.Visit(m.Object);
                    foreach (Expression arg in m.Arguments) { 
                        this.Visit(arg);
                        break; // Only follow the extension method 'this' 
                    } 
                    return m;
                } 

            }
        }
 
        private void ValidateTypeGraphAcyclic() {
            IEnumerable edges = this.includes.Values; 
            int removed = 0; 

            for (int loop = 0; loop < this.includes.Count; ++loop) { 
                // Build a list of all edge targets.
                HashSet edgeTargets = new HashSet();
                foreach (MemberInfo edge in edges) {
                    edgeTargets.Add(GetIncludeTarget(edge)); 
                }
                // Remove all edges with sources matching no target. 
                List newEdges = new List(); 
                bool someRemoved = false;
                foreach (MemberInfo edge in edges) { 
                    if (edgeTargets.Where(et=>et.IsAssignableFrom(edge.DeclaringType) || edge.DeclaringType.IsAssignableFrom(et)).Any()) {
                        newEdges.Add(edge);
                    }
                    else { 
                        ++removed;
                        someRemoved = true; 
                        if (removed == this.includes.Count) 
                            return;
                    } 
                }
                if (!someRemoved) {
                    throw Error.IncludeCycleNotAllowed(); // No edges removed, there must be a loop.
                } 
                edges = newEdges;
            } 
            throw new InvalidOperationException("Bug in ValidateTypeGraphAcyclic"); // Getting here means a bug. 
        }
 
        private static Type GetIncludeTarget(MemberInfo mi) {
            Type mt = System.Data.Linq.SqlClient.TypeSystem.GetMemberType(mi);
            if (mt.IsGenericType) {
                return mt.GetGenericArguments()[0]; 
            }
            return mt; 
        } 

        private static void ValidateSubqueryMember(MemberInfo mi) { 
            Type memberType = System.Data.Linq.SqlClient.TypeSystem.GetMemberType(mi);
            if (memberType == null) {
                throw Error.SubqueryNotSupportedOn(mi);
            } 
            if (!typeof(IEnumerable).IsAssignableFrom(memberType)) {
                throw Error.SubqueryNotSupportedOnType(mi.Name, mi.DeclaringType); 
            } 
        }
 
        private static void ValidateSubqueryExpression(LambdaExpression subquery) {
            if (!typeof(IEnumerable).IsAssignableFrom(subquery.Body.Type)) {
                throw Error.SubqueryMustBeSequence();
            } 
            new SubqueryValidator().VisitLambda(subquery);
        } 
 
        /// 
        /// Ensure that the subquery follows the rules for subqueries. 
        /// 
        private class SubqueryValidator : System.Data.Linq.SqlClient.ExpressionVisitor {
            bool isTopLevel = true;
            internal override Expression VisitMethodCall(MethodCallExpression m) { 
                bool was = isTopLevel;
                try { 
                    if (isTopLevel && !SubqueryRules.IsSupportedTopLevelMethod(m.Method)) 
                        throw Error.SubqueryDoesNotSupportOperator(m.Method.Name);
                    isTopLevel = false; 
                    return base.VisitMethodCall(m);
                }
                finally {
                    isTopLevel = was; 
                }
            } 
        } 

        ///  
        /// Whether there have been LoadOptions specified.
        /// 
        internal bool IsEmpty {
            get { return this.includes.Count == 0 && this.subqueries.Count == 0; } 
        }
    } 
} 

// 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