File: DependencyObjectValidator.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (225 lines) | stat: -rw-r--r-- 12,217 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
namespace System.Workflow.ComponentModel.Compiler
{
    using System;
    using System.Reflection;
    using System.Collections;
    using System.Collections.Generic;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.ComponentModel.Serialization;

    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public class DependencyObjectValidator : Validator
    {
        public override ValidationErrorCollection Validate(ValidationManager manager, object obj)
        {
            if (manager == null)
                throw new ArgumentNullException("manager");
            if (obj == null)
                throw new ArgumentNullException("obj");

            ValidationErrorCollection validationErrors = base.Validate(manager, obj);
            DependencyObject dependencyObject = obj as DependencyObject;
            if (dependencyObject == null)
                throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(DependencyObject).FullName), "obj");

            ArrayList allProperties = new ArrayList();

            // Validate all the settable dependency properties
            // attached property can not be found through the call to DependencyProperty.FromType()
            foreach (DependencyProperty prop in DependencyProperty.FromType(dependencyObject.GetType()))
            {
                // This property is attached to some other object.  We should not validate it here
                // because the context is wrong.
                if (!prop.IsAttached)
                    allProperties.Add(prop);
            }
            // 


            foreach (DependencyProperty prop in dependencyObject.MetaDependencyProperties)
            {
                if (prop.IsAttached)
                {
                    if (obj.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance) == null)
                        allProperties.Add(prop);
                }
            }

            foreach (DependencyProperty prop in allProperties)
            {
                object[] validationVisibilityAtrributes = prop.DefaultMetadata.GetAttributes(typeof(ValidationOptionAttribute));
                ValidationOption validationVisibility = (validationVisibilityAtrributes.Length > 0) ? ((ValidationOptionAttribute)validationVisibilityAtrributes[0]).ValidationOption : ValidationOption.Optional;
                if (validationVisibility != ValidationOption.None)
                    validationErrors.AddRange(ValidateDependencyProperty(dependencyObject, prop, manager));
            }

            return validationErrors;
        }

        private ValidationErrorCollection ValidateDependencyProperty(DependencyObject dependencyObject, DependencyProperty dependencyProperty, ValidationManager manager)
        {
            ValidationErrorCollection errors = new ValidationErrorCollection();

            Attribute[] validationVisibilityAtrributes = dependencyProperty.DefaultMetadata.GetAttributes(typeof(ValidationOptionAttribute));
            ValidationOption validationVisibility = (validationVisibilityAtrributes.Length > 0) ? ((ValidationOptionAttribute)validationVisibilityAtrributes[0]).ValidationOption : ValidationOption.Optional;

            Activity activity = manager.Context[typeof(Activity)] as Activity;
            if (activity == null)
                throw new InvalidOperationException(SR.GetString(SR.Error_ContextStackItemMissing, typeof(Activity).FullName));

            PropertyValidationContext propertyValidationContext = new PropertyValidationContext(activity, dependencyProperty);
            manager.Context.Push(propertyValidationContext);

            try
            {
                if (dependencyProperty.DefaultMetadata.DefaultValue != null)
                {
                    if (!dependencyProperty.PropertyType.IsValueType &&
                        dependencyProperty.PropertyType != typeof(string))
                    {
                        errors.Add(new ValidationError(SR.GetString(SR.Error_PropertyDefaultIsReference, dependencyProperty.Name), ErrorNumbers.Error_PropertyDefaultIsReference));
                    }
                    else if (!dependencyProperty.PropertyType.IsAssignableFrom(dependencyProperty.DefaultMetadata.DefaultValue.GetType()))
                    {
                        errors.Add(new ValidationError(SR.GetString(SR.Error_PropertyDefaultTypeMismatch, dependencyProperty.Name, dependencyProperty.PropertyType.FullName, dependencyProperty.DefaultMetadata.DefaultValue.GetType().FullName), ErrorNumbers.Error_PropertyDefaultTypeMismatch));
                    }
                }

                // If an event is of type Bind, GetBinding will return the Bind object.
                object propValue = null;
                if (dependencyObject.IsBindingSet(dependencyProperty))
                    propValue = dependencyObject.GetBinding(dependencyProperty);
                else if (!dependencyProperty.IsEvent)
                    propValue = dependencyObject.GetValue(dependencyProperty);

                if (propValue == null || propValue == dependencyProperty.DefaultMetadata.DefaultValue)
                {
                    if (dependencyProperty.IsEvent)
                    {
                        // Is this added through "+=" in InitializeComponent?  If so, the value should be in the instance properties hashtable
                        // If none of these, its value is stored in UserData at design time.
                        propValue = dependencyObject.GetHandler(dependencyProperty);
                        if (propValue == null)
                            propValue = WorkflowMarkupSerializationHelpers.GetEventHandlerName(dependencyObject, dependencyProperty.Name);

                        if (propValue is string && !string.IsNullOrEmpty((string)propValue))
                            errors.AddRange(ValidateEvent(activity, dependencyProperty, propValue, manager));
                    }
                    else
                    {
                        // Maybe this is an instance property.
                        propValue = dependencyObject.GetValue(dependencyProperty);
                    }
                }

                // Be careful before changing this. This is the (P || C) validation validation
                // i.e. validate properties being set only if Parent is set or 
                // a child exists.
                bool checkNotSet = (activity.Parent != null) || ((activity is CompositeActivity) && (((CompositeActivity)activity).EnabledActivities.Count != 0));

                if (validationVisibility == ValidationOption.Required &&
                    (propValue == null || (propValue is string && string.IsNullOrEmpty((string)propValue))) &&
                    (dependencyProperty.DefaultMetadata.IsMetaProperty) &&
                    checkNotSet)
                {
                    errors.Add(ValidationError.GetNotSetValidationError(GetFullPropertyName(manager)));
                }
                else if (propValue != null)
                {
                    if (propValue is IList)
                    {
                        PropertyValidationContext childContext = new PropertyValidationContext(propValue, null, String.Empty);
                        manager.Context.Push(childContext);

                        try
                        {
                            foreach (object child in (IList)propValue)
                                errors.AddRange(ValidationHelpers.ValidateObject(manager, child));
                        }
                        finally
                        {
                            System.Diagnostics.Debug.Assert(manager.Context.Current == childContext, "Unwinding contextStack: the item that is about to be popped is not the one we pushed.");
                            manager.Context.Pop();
                        }
                    }
                    else if (dependencyProperty.ValidatorType != null)
                    {
                        Validator validator = null;
                        try
                        {
                            validator = Activator.CreateInstance(dependencyProperty.ValidatorType) as Validator;
                            if (validator == null)
                                errors.Add(new ValidationError(SR.GetString(SR.Error_CreateValidator, dependencyProperty.ValidatorType.FullName), ErrorNumbers.Error_CreateValidator));
                            else
                                errors.AddRange(validator.Validate(manager, propValue));
                        }
                        catch
                        {
                            errors.Add(new ValidationError(SR.GetString(SR.Error_CreateValidator, dependencyProperty.ValidatorType.FullName), ErrorNumbers.Error_CreateValidator));
                        }
                    }
                    else
                    {
                        errors.AddRange(ValidationHelpers.ValidateObject(manager, propValue));
                    }
                }
            }
            finally
            {
                System.Diagnostics.Debug.Assert(manager.Context.Current == propertyValidationContext, "Unwinding contextStack: the item that is about to be popped is not the one we pushed.");
                manager.Context.Pop();
            }

            return errors;
        }

        private ValidationErrorCollection ValidateEvent(Activity activity, DependencyProperty dependencyProperty, object propValue, ValidationManager manager)
        {
            ValidationErrorCollection validationErrors = new ValidationErrorCollection();

            if (propValue is string && !string.IsNullOrEmpty((string)propValue))
            {
                bool handlerExists = false;
                Type objType = null;
                Activity rootActivity = Helpers.GetRootActivity(activity);
                Activity enclosingActivity = Helpers.GetEnclosingActivity(activity);
                string typeName = rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty) as string;
                if (rootActivity == enclosingActivity && !string.IsNullOrEmpty(typeName))
                {
                    ITypeProvider typeProvider = manager.GetService(typeof(ITypeProvider)) as ITypeProvider;
                    if (typeProvider == null)
                        throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));

                    objType = typeProvider.GetType(typeName);
                }
                else
                    objType = enclosingActivity.GetType();

                if (objType != null)
                {
                    MethodInfo invokeMethod = dependencyProperty.PropertyType.GetMethod("Invoke");
                    if (invokeMethod != null)
                    {
                        // resolve the method
                        List<Type> paramTypes = new List<Type>();
                        foreach (ParameterInfo paramInfo in invokeMethod.GetParameters())
                            paramTypes.Add(paramInfo.ParameterType);

                        MethodInfo methodInfo = Helpers.GetMethodExactMatch(objType, propValue as string, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy, null, paramTypes.ToArray(), null);
                        if (methodInfo != null && TypeProvider.IsAssignable(invokeMethod.ReturnType, methodInfo.ReturnType))
                            handlerExists = true;
                    }
                }

                if (!handlerExists)
                {
                    ValidationError error = new ValidationError(SR.GetString(SR.Error_CantResolveEventHandler, dependencyProperty.Name, propValue as string), ErrorNumbers.Error_CantResolveEventHandler);
                    error.PropertyName = GetFullPropertyName(manager);
                    validationErrors.Add(error);
                }
            }

            return validationErrors;
        }
    }
}