You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			303 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			303 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|   | // --------------------------------------------------------------------------- | ||
|  | // Copyright (C) 2006 Microsoft Corporation All Rights Reserved | ||
|  | // --------------------------------------------------------------------------- | ||
|  | 
 | ||
|  | #define CODE_ANALYSIS | ||
|  | using System.CodeDom; | ||
|  | using System.Diagnostics.CodeAnalysis; | ||
|  | using System.Globalization; | ||
|  | using System.Text; | ||
|  | using System.Workflow.ComponentModel; | ||
|  | using System.Workflow.ComponentModel.Compiler; | ||
|  | using System.Workflow.Activities.Common; | ||
|  | 
 | ||
|  | namespace System.Workflow.Activities.Rules | ||
|  | { | ||
|  |     #region RuleExpressionWalker | ||
|  | 
 | ||
|  |     public static class RuleExpressionWalker | ||
|  |     { | ||
|  |         #region IRuleExpression wrapper factories for CodeDom | ||
|  | 
 | ||
|  |         class CustomExpressionWrapper : RuleExpressionInternal | ||
|  |         { | ||
|  |             private IRuleExpression ruleExpr; | ||
|  | 
 | ||
|  |             internal CustomExpressionWrapper(IRuleExpression ruleExpr) | ||
|  |             { | ||
|  |                 this.ruleExpr = ruleExpr; | ||
|  |             } | ||
|  | 
 | ||
|  |             internal override void AnalyzeUsage(CodeExpression expression, RuleAnalysis analysis, bool isRead, bool isWritten, RulePathQualifier qualifier) | ||
|  |             { | ||
|  |                 ruleExpr.AnalyzeUsage(analysis, isRead, isWritten, qualifier); | ||
|  |             } | ||
|  | 
 | ||
|  |             internal override CodeExpression Clone(CodeExpression expression) | ||
|  |             { | ||
|  |                 return ruleExpr.Clone(); | ||
|  |             } | ||
|  | 
 | ||
|  |             internal override void Decompile(CodeExpression expression, StringBuilder decompilation, CodeExpression parentExpression) | ||
|  |             { | ||
|  |                 ruleExpr.Decompile(decompilation, parentExpression); | ||
|  |             } | ||
|  | 
 | ||
|  |             internal override RuleExpressionResult Evaluate(CodeExpression expression, RuleExecution execution) | ||
|  |             { | ||
|  |                 return ruleExpr.Evaluate(execution); | ||
|  |             } | ||
|  | 
 | ||
|  |             internal override bool Match(CodeExpression leftExpression, CodeExpression rightExpression) | ||
|  |             { | ||
|  |                 return ruleExpr.Match(rightExpression); | ||
|  |             } | ||
|  | 
 | ||
|  |             internal override RuleExpressionInfo Validate(CodeExpression expression, RuleValidation validation, bool isWritten) | ||
|  |             { | ||
|  |                 return ruleExpr.Validate(validation, isWritten); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         class TypeWrapperTuple | ||
|  |         { | ||
|  |             internal Type codeDomType; | ||
|  |             internal RuleExpressionInternal internalExpression; | ||
|  | 
 | ||
|  |             internal TypeWrapperTuple(Type type, RuleExpressionInternal internalExpression) | ||
|  |             { | ||
|  |                 this.codeDomType = type; | ||
|  |                 this.internalExpression = internalExpression; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         static TypeWrapperTuple[] typeWrappers = new TypeWrapperTuple[] { | ||
|  |             new TypeWrapperTuple(typeof(CodeThisReferenceExpression), new ThisExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodePrimitiveExpression), new PrimitiveExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeFieldReferenceExpression), new FieldReferenceExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodePropertyReferenceExpression), new PropertyReferenceExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeBinaryOperatorExpression), new BinaryExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeMethodInvokeExpression), new MethodInvokeExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeIndexerExpression), new IndexerPropertyExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeArrayIndexerExpression), new ArrayIndexerExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeDirectionExpression), new DirectionExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeTypeReferenceExpression), new TypeReferenceExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeCastExpression), new CastExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeObjectCreateExpression), new ObjectCreateExpression()), | ||
|  |             new TypeWrapperTuple(typeof(CodeArrayCreateExpression), new ArrayCreateExpression()) | ||
|  |         }; | ||
|  | 
 | ||
|  |         private static RuleExpressionInternal GetExpression(CodeExpression expression) | ||
|  |         { | ||
|  |             Type exprType = expression.GetType(); | ||
|  |             int numTypeWrappers = typeWrappers.Length; | ||
|  |             for (int i = 0; i < numTypeWrappers; ++i) | ||
|  |             { | ||
|  |                 TypeWrapperTuple tuple = typeWrappers[i]; | ||
|  |                 if (exprType == tuple.codeDomType) | ||
|  |                     return tuple.internalExpression; | ||
|  |             } | ||
|  | 
 | ||
|  |             // It's not a builtin one... try a user extension expression. | ||
|  |             IRuleExpression ruleExpr = expression as IRuleExpression; | ||
|  |             if (ruleExpr != null) | ||
|  |                 return new CustomExpressionWrapper(ruleExpr); | ||
|  | 
 | ||
|  |             return null; | ||
|  |         } | ||
|  | 
 | ||
|  |         #endregion | ||
|  | 
 | ||
|  |         public static RuleExpressionInfo Validate(RuleValidation validation, CodeExpression expression, bool isWritten) | ||
|  |         { | ||
|  |             if (validation == null) | ||
|  |                 throw new ArgumentNullException("validation"); | ||
|  | 
 | ||
|  |             // See if we've visited this node before. | ||
|  |             // Always check if written = true | ||
|  |             RuleExpressionInfo resultExprInfo = null; | ||
|  |             if (!isWritten) | ||
|  |                 resultExprInfo = validation.ExpressionInfo(expression); | ||
|  |             if (resultExprInfo == null) | ||
|  |             { | ||
|  |                 // First time we've seen this node. | ||
|  |                 RuleExpressionInternal ruleExpr = GetExpression(expression); | ||
|  |                 if (ruleExpr == null) | ||
|  |                 { | ||
|  |                     string message = string.Format(CultureInfo.CurrentCulture, Messages.CodeExpressionNotHandled, expression.GetType().FullName); | ||
|  |                     ValidationError error = new ValidationError(message, ErrorNumbers.Error_CodeExpressionNotHandled); | ||
|  |                     error.UserData[RuleUserDataKeys.ErrorObject] = expression; | ||
|  | 
 | ||
|  |                     if (validation.Errors == null) | ||
|  |                     { | ||
|  |                         string typeName = string.Empty; | ||
|  |                         if ((validation.ThisType != null) && (validation.ThisType.Name != null)) | ||
|  |                         { | ||
|  |                             typeName = validation.ThisType.Name; | ||
|  |                         } | ||
|  | 
 | ||
|  |                         string exceptionMessage = string.Format( | ||
|  |                             CultureInfo.CurrentCulture, Messages.ErrorsCollectionMissing, typeName); | ||
|  | 
 | ||
|  |                         throw new InvalidOperationException(exceptionMessage); | ||
|  |                     } | ||
|  |                     else | ||
|  |                     { | ||
|  |                         validation.Errors.Add(error); | ||
|  |                     } | ||
|  | 
 | ||
|  |                     return null; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 resultExprInfo = validation.ValidateSubexpression(expression, ruleExpr, isWritten); | ||
|  |             } | ||
|  | 
 | ||
|  |             return resultExprInfo; | ||
|  |         } | ||
|  | 
 | ||
|  |         public static void AnalyzeUsage(RuleAnalysis analysis, CodeExpression expression, bool isRead, bool isWritten, RulePathQualifier qualifier) | ||
|  |         { | ||
|  |             if (analysis == null) | ||
|  |                 throw new ArgumentNullException("analysis"); | ||
|  | 
 | ||
|  |             RuleExpressionInternal ruleExpr = GetExpression(expression); | ||
|  |             ruleExpr.AnalyzeUsage(expression, analysis, isRead, isWritten, qualifier); | ||
|  |         } | ||
|  | 
 | ||
|  |         public static RuleExpressionResult Evaluate(RuleExecution execution, CodeExpression expression) | ||
|  |         { | ||
|  |             if (execution == null) | ||
|  |                 throw new ArgumentNullException("execution"); | ||
|  | 
 | ||
|  |             RuleExpressionInternal ruleExpr = GetExpression(expression); | ||
|  |             return ruleExpr.Evaluate(expression, execution); | ||
|  |         } | ||
|  | 
 | ||
|  |         [SuppressMessage("Microsoft.Naming", "CA1720:AvoidTypeNamesInParameters", MessageId = "0#")] | ||
|  |         public static void Decompile(StringBuilder stringBuilder, CodeExpression expression, CodeExpression parentExpression) | ||
|  |         { | ||
|  |             RuleExpressionInternal ruleExpr = GetExpression(expression); | ||
|  |             ruleExpr.Decompile(expression, stringBuilder, parentExpression); | ||
|  |         } | ||
|  | 
 | ||
|  |         [SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] | ||
|  |         public static bool Match(CodeExpression firstExpression, CodeExpression secondExpression) | ||
|  |         { | ||
|  |             // If they're both null, they match. | ||
|  |             if (firstExpression == null && secondExpression == null) | ||
|  |                 return true; | ||
|  | 
 | ||
|  |             // If only one of them is null, there's no match. | ||
|  |             if (firstExpression == null || secondExpression == null) | ||
|  |                 return false; | ||
|  | 
 | ||
|  |             if (firstExpression.GetType() != secondExpression.GetType()) | ||
|  |                 return false; | ||
|  | 
 | ||
|  |             RuleExpressionInternal ruleExpr1 = GetExpression(firstExpression); | ||
|  |             return ruleExpr1.Match(firstExpression, secondExpression); | ||
|  |         } | ||
|  | 
 | ||
|  |         public static CodeExpression Clone(CodeExpression originalExpression) | ||
|  |         { | ||
|  |             if (originalExpression == null) | ||
|  |                 return null; | ||
|  | 
 | ||
|  |             RuleExpressionInternal ruleExpr = GetExpression(originalExpression); | ||
|  |             CodeExpression newExpr = ruleExpr.Clone(originalExpression); | ||
|  | 
 | ||
|  |             ConditionHelper.CloneUserData(originalExpression, newExpr); | ||
|  | 
 | ||
|  |             return newExpr; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     #endregion | ||
|  | 
 | ||
|  |     #region CodeDomStatementWalker (internal) | ||
|  | 
 | ||
|  |     internal static class CodeDomStatementWalker | ||
|  |     { | ||
|  |         #region RuleCodeDomStatement wrapper factories for CodeDom | ||
|  | 
 | ||
|  |         private delegate RuleCodeDomStatement WrapperCreator(CodeStatement statement); | ||
|  | 
 | ||
|  |         private static RuleCodeDomStatement GetStatement(CodeStatement statement) | ||
|  |         { | ||
|  |             Type statementType = statement.GetType(); | ||
|  | 
 | ||
|  |             RuleCodeDomStatement wrapper = null; | ||
|  |             if (statementType == typeof(CodeExpressionStatement)) | ||
|  |             { | ||
|  |                 wrapper = ExpressionStatement.Create(statement); | ||
|  |             } | ||
|  |             else if (statementType == typeof(CodeAssignStatement)) | ||
|  |             { | ||
|  |                 wrapper = AssignmentStatement.Create(statement); | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 string message = string.Format(CultureInfo.CurrentCulture, Messages.CodeStatementNotHandled, statement.GetType().FullName); | ||
|  |                 NotSupportedException exception = new NotSupportedException(message); | ||
|  |                 exception.Data[RuleUserDataKeys.ErrorObject] = statement; | ||
|  |                 throw exception; | ||
|  |             } | ||
|  | 
 | ||
|  |             return wrapper; | ||
|  |         } | ||
|  | 
 | ||
|  |         #endregion | ||
|  | 
 | ||
|  |         internal static bool Validate(RuleValidation validation, CodeStatement statement) | ||
|  |         { | ||
|  |             RuleCodeDomStatement ruleStmt = GetStatement(statement); | ||
|  |             return ruleStmt.Validate(validation); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static void Execute(RuleExecution execution, CodeStatement statement) | ||
|  |         { | ||
|  |             RuleCodeDomStatement ruleStmt = GetStatement(statement); | ||
|  |             ruleStmt.Execute(execution); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static void AnalyzeUsage(RuleAnalysis analysis, CodeStatement statement) | ||
|  |         { | ||
|  |             RuleCodeDomStatement ruleStmt = GetStatement(statement); | ||
|  |             ruleStmt.AnalyzeUsage(analysis); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static void Decompile(StringBuilder stringBuilder, CodeStatement statement) | ||
|  |         { | ||
|  |             RuleCodeDomStatement ruleStmt = GetStatement(statement); | ||
|  |             ruleStmt.Decompile(stringBuilder); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool Match(CodeStatement firstStatement, CodeStatement secondStatement) | ||
|  |         { | ||
|  |             // If they're both null, they match. | ||
|  |             if (firstStatement == null && secondStatement == null) | ||
|  |                 return true; | ||
|  | 
 | ||
|  |             // If only one of them is null, there's no match. | ||
|  |             if (firstStatement == null || secondStatement == null) | ||
|  |                 return false; | ||
|  | 
 | ||
|  |             if (firstStatement.GetType() != secondStatement.GetType()) | ||
|  |                 return false; | ||
|  | 
 | ||
|  |             RuleCodeDomStatement ruleStmt = GetStatement(firstStatement); | ||
|  |             return ruleStmt.Match(secondStatement); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static CodeStatement Clone(CodeStatement statement) | ||
|  |         { | ||
|  |             if (statement == null) | ||
|  |                 return null; | ||
|  |             RuleCodeDomStatement ruleStmt = GetStatement(statement); | ||
|  |             return ruleStmt.Clone(); | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     #endregion | ||
|  | } |