ConstraintParser.cs :  » 2.6.4-mono-.net-core » System.ComponentModel » System » ComponentModel » Composition » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.ComponentModel 
System.ComponentModel » System » ComponentModel » Composition » ConstraintParser.cs
// -----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.Internal;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.ComponentModel.Composition.Primitives;

namespace System.ComponentModel.Composition{
    public class ContraintParser
    {
        private static readonly PropertyInfo _exportDefinitionContractNameProperty = typeof(ExportDefinition).GetProperty("ContractName");
        private static readonly PropertyInfo _exportDefinitionMetadataProperty = typeof(ExportDefinition).GetProperty("Metadata");
        private static readonly MethodInfo _metadataContainsKeyMethod = typeof(IDictionary<string, object>).GetMethod("ContainsKey");
        private static readonly MethodInfo _metadataItemMethod = typeof(IDictionary<string, object>).GetMethod("get_Item");
        private static readonly MethodInfo _typeIsInstanceOfTypeMethod = typeof(Type).GetMethod("IsInstanceOfType");

        public static bool TryParseConstraint(Expression<Func<ExportDefinition, bool>> constraint, out string contractName, out IEnumerable<KeyValuePair<string, Type>> requiredMetadata)
        {
            contractName = null;
            requiredMetadata = null;

            List<KeyValuePair<string, Type>> requiredMetadataList = new List<KeyValuePair<string, Type>>();
            foreach (Expression expression in SplitConstraintBody(constraint.Body))
            {
                // First try to parse as a contract, if we don't have one already
                if (contractName == null && TryParseExpressionAsContractConstraintBody(expression, constraint.Parameters[0], out contractName))
                {
                    continue;
                }

                // Then try to parse as a required metadata item name
                string requiredMetadataItemName = null;
                Type requiredMetadataItemType = null;
                if (TryParseExpressionAsMetadataConstraintBody(expression, constraint.Parameters[0], out requiredMetadataItemName, out requiredMetadataItemType))
                {
                    requiredMetadataList.Add(new KeyValuePair<string, Type>(requiredMetadataItemName, requiredMetadataItemType));
                }

                // Just skip the expressions we don't understand  
            }

            // ContractName should have been set already, just need to set metadata
            requiredMetadata = requiredMetadataList;
            return true;
        }


        private static IEnumerable<Expression> SplitConstraintBody(Expression expression)
        {
            Assert.IsNotNull(expression);

            // The expression we know about should be a set of nested AndAlso's, we
            // need to flatten them into one list. we do this iteratively, as 
            // recursion will create too much of a memory churn.
            Stack<Expression> expressions = new Stack<Expression>();
            expressions.Push(expression);

            while (expressions.Count > 0)
            {
                Expression current = expressions.Pop();
                if (current.NodeType == ExpressionType.AndAlso)
                {
                    BinaryExpression andAlso = (BinaryExpression)current;
                    // Push right first - this preserves the ordering of the expression, which will force
                    // the contract constraint to come up first as the callers are optimized for this form
                    expressions.Push(andAlso.Right);
                    expressions.Push(andAlso.Left);
                    continue;
                }

                yield return current;
            }
        }

        private static bool TryParseExpressionAsContractConstraintBody(Expression expression, Expression parameter, out string contractName)
        {
            contractName = null;

            // The expression should be an '==' expression
            if (expression.NodeType != ExpressionType.Equal)
            {
                return false;
            }

            BinaryExpression contractConstraintExpression = (BinaryExpression)expression;

            // First try item.ContractName == "Value"
            if (TryParseContractNameFromEqualsExpression(contractConstraintExpression.Left, contractConstraintExpression.Right, parameter, out contractName))
            {
                return true;
            }

            // Then try "Value == item.ContractName
            if (TryParseContractNameFromEqualsExpression(contractConstraintExpression.Right, contractConstraintExpression.Left, parameter, out contractName))
            {
                return true;
            }

            return false;
        }

        private static bool TryParseContractNameFromEqualsExpression(Expression left, Expression right, Expression parameter, out string contractName)
        {
            contractName = null;

            // The left should be access to property "Contract" applied to the parameter
            MemberExpression targetMember = left as MemberExpression;
            if (targetMember == null)
            {
                return false;
            }

            if ((targetMember.Member != _exportDefinitionContractNameProperty) || (targetMember.Expression != parameter))
            {
                return false;
            }

            // Right should a constant expression containing the contract name
            ConstantExpression contractNameConstant = right as ConstantExpression;
            if (contractNameConstant == null)
            {
                return false;
            }

            if (!TryParseConstant<string>(contractNameConstant, out contractName))
            {
                return false;
            }

            return true;
        }

        private static bool TryParseExpressionAsMetadataConstraintBody(Expression expression, Expression parameter, out string requiredMetadataKey, out Type requiredMetadataType)
        {
            Assumes.NotNull(expression, parameter);

            requiredMetadataKey = null;
            requiredMetadataType = null;

            // Should be a call to Type.IsInstanceofType on definition.Metadata[key]
            MethodCallExpression outerMethodCall = expression as MethodCallExpression;
            if (outerMethodCall == null)
            {
                return false;
            }

            // Make sure that the right method ie being called
            if (outerMethodCall.Method != _typeIsInstanceOfTypeMethod)
            {
                return false;
            }
            Assumes.IsTrue(outerMethodCall.Arguments.Count == 1);


            // 'this' should be a constant expression pointing at a Type object
            ConstantExpression targetType = outerMethodCall.Object as ConstantExpression;
            if(!TryParseConstant<Type>(targetType, out requiredMetadataType))
            {
                return false;
            }

            // SHould be a call to get_Item
            MethodCallExpression methodCall = outerMethodCall.Arguments[0] as MethodCallExpression;
            if (methodCall == null)
            {
                return false;
            }

            if (methodCall.Method != _metadataItemMethod)
            {
                return false;
            }

            // Make sure the method is being called on the right object            
            MemberExpression targetMember = methodCall.Object as MemberExpression;
            if (targetMember == null)
            {
                return false;
            }

            if ((targetMember.Expression != parameter) || (targetMember.Member != _exportDefinitionMetadataProperty))
            {
                return false;
            }

            // There should only ever be one argument; otherwise, 
            // we've got the wrong IDictionary.get_Item method.
            Assumes.IsTrue(methodCall.Arguments.Count == 1);

            // Argument should a constant expression containing the metadata key
            ConstantExpression requiredMetadataKeyConstant = methodCall.Arguments[0] as ConstantExpression;
            if (requiredMetadataKeyConstant == null)
            {
                return false;
            }

            if (!TryParseConstant<string>(requiredMetadataKeyConstant, out requiredMetadataKey))
            {
                return false;
            }

            return true;
        }

        private static bool TryParseConstant<T>(ConstantExpression constant, out T result)
            where T : class
        {
            Assumes.NotNull(constant);

            if (constant.Type == typeof(T) && constant.Value != null)
            {
                result = (T)constant.Value;
                return true;
            }

            result = default(T);
            return false;
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.