1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4 
5 namespace System.Activities.Validation
6 {
7     using System;
8     using System.Collections.Generic;
9     using System.Diagnostics.CodeAnalysis;
10     using System.Runtime;
11     using System.Windows.Markup;
12     using System.Collections.ObjectModel;
13 
14     public abstract class Constraint : NativeActivity
15     {
16         public const string ValidationErrorListPropertyName = "System.Activities.Validation.Constraint.ValidationErrorList";
17 
18         internal const string ToValidateArgumentName = "ToValidate";
19         internal const string ValidationErrorListArgumentName = "ViolationList";
20         internal const string ToValidateContextArgumentName = "ToValidateContext";
21 
22         RuntimeArgument toValidate;
23         RuntimeArgument violationList;
24         RuntimeArgument toValidateContext;
25 
Constraint()26         internal Constraint()
27         {
28             this.toValidate = new RuntimeArgument(ToValidateArgumentName, typeof(object), ArgumentDirection.In);
29             this.toValidateContext = new RuntimeArgument(ToValidateContextArgumentName, typeof(ValidationContext), ArgumentDirection.In);
30             this.violationList = new RuntimeArgument(ValidationErrorListArgumentName, typeof(IList<ValidationError>), ArgumentDirection.Out);
31         }
32 
AddValidationError(NativeActivityContext context, ValidationError error)33         public static void AddValidationError(NativeActivityContext context, ValidationError error)
34         {
35             List<ValidationError> validationErrorList = context.Properties.Find(ValidationErrorListPropertyName) as List<ValidationError>;
36 
37             if (validationErrorList == null)
38             {
39                 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.AddValidationErrorMustBeCalledFromConstraint(typeof(Constraint).Name)));
40             }
41 
42             validationErrorList.Add(error);
43         }
44 
CacheMetadata(NativeActivityMetadata metadata)45         protected override void CacheMetadata(NativeActivityMetadata metadata)
46         {
47             metadata.SetArgumentsCollection(
48                 new Collection<RuntimeArgument>
49                 {
50                     this.toValidate,
51                     this.violationList,
52                     this.toValidateContext
53                 });
54         }
55 
Execute(NativeActivityContext context)56         protected override void Execute(NativeActivityContext context)
57         {
58             object objectToValidate = this.toValidate.Get<object>(context);
59             ValidationContext objectToValidateContext = this.toValidateContext.Get<ValidationContext>(context);
60 
61             if (objectToValidate == null)
62             {
63                 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CannotValidateNullObject(typeof(Constraint).Name, this.DisplayName)));
64             }
65 
66             if (objectToValidateContext == null)
67             {
68                 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ValidationContextCannotBeNull(typeof(Constraint).Name, this.DisplayName)));
69             }
70 
71             List<ValidationError> validationErrorList = new List<ValidationError>(1);
72             context.Properties.Add(ValidationErrorListPropertyName, validationErrorList);
73 
74             this.violationList.Set(context, validationErrorList);
75 
76             OnExecute(context, objectToValidate, objectToValidateContext);
77         }
78 
79         [SuppressMessage(FxCop.Category.Naming, FxCop.Rule.IdentifiersShouldNotContainTypeNames,
80             Justification = "Can't replace object with Object because of casing rules")]
OnExecute(NativeActivityContext context, object objectToValidate, ValidationContext objectToValidateContext)81         protected abstract void OnExecute(NativeActivityContext context, object objectToValidate, ValidationContext objectToValidateContext);
82     }
83 
84     [ContentProperty("Body")]
85     public sealed class Constraint<T> : Constraint
86     {
Constraint()87         public Constraint()
88         {
89         }
90 
91         public ActivityAction<T, ValidationContext> Body
92         {
93             get;
94             set;
95         }
CacheMetadata(NativeActivityMetadata metadata)96         protected override void CacheMetadata(NativeActivityMetadata metadata)
97         {
98             base.CacheMetadata(metadata);
99 
100             if (this.Body != null)
101             {
102                 metadata.SetDelegatesCollection(new Collection<ActivityDelegate> { this.Body });
103             }
104         }
105 
OnExecute(NativeActivityContext context, object objectToValidate, ValidationContext objectToValidateContext)106         protected override void OnExecute(NativeActivityContext context, object objectToValidate, ValidationContext objectToValidateContext)
107         {
108             if (this.Body != null)
109             {
110                 context.ScheduleAction(this.Body, (T)objectToValidate, objectToValidateContext);
111             }
112         }
113     }
114 }
115