1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.Components
.Validator
18 using System
.Collections
;
19 using System
.Reflection
;
22 /// Coordinates the gathering and execution of validators.
23 /// <seealso cref="IValidatorRegistry"/>
26 /// ValidatorRunner runner = new ValidatorRunner(new CachedValidationRegistry());
28 /// if (!runner.IsValid(customer))
30 /// // do something as the Customer instance is not valid
33 public class ValidatorRunner
35 private readonly static IDictionary type2Validator
;
36 private readonly IDictionary extendedProperties
= new Hashtable();
37 private readonly bool inferValidators
;
38 private readonly IDictionary errorPerInstance
;
39 private readonly IValidatorRegistry registry
;
41 static ValidatorRunner()
43 type2Validator
= new Hashtable();
44 type2Validator
[typeof(Int16
)] = typeof(IntegerValidator
);
45 type2Validator
[typeof(Int32
)] = typeof(IntegerValidator
);
46 type2Validator
[typeof(Int64
)] = typeof(IntegerValidator
);
47 type2Validator
[typeof(decimal)] = typeof(DecimalValidator
);
48 type2Validator
[typeof(Single
)] = typeof(SingleValidator
);
49 type2Validator
[typeof(double)] = typeof(DoubleValidator
);
50 type2Validator
[typeof(DateTime
)] = typeof(DateTimeValidator
);
53 public IDictionary ExtendedProperties
55 get { return extendedProperties; }
59 /// Initializes a new instance of the <see cref="ValidatorRunner"/> class.
61 /// <param name="registry">The instance registry.</param>
62 public ValidatorRunner(IValidatorRegistry registry
) : this(true, registry
)
67 /// Initializes a new instance of the <see cref="ValidatorRunner"/> class.
69 /// <param name="inferValidators">if <c>true</c>, the runner will try
70 /// to infer un-declared validators based on property types</param>
71 /// <param name="registry">The registry.</param>
72 public ValidatorRunner(bool inferValidators
, IValidatorRegistry registry
)
74 if (registry
== null) throw new ArgumentNullException("registry");
76 errorPerInstance
= new Hashtable();
78 this.inferValidators
= inferValidators
;
79 this.registry
= registry
;
83 /// Determines whether the specified instance is valid.
85 /// All validators are run.
88 /// <param name="objectInstance">The object instance to be validated (cannot be null).</param>
90 /// <see langword="true"/> if the specified obj is valid; otherwise, <see langword="false"/>.
92 public bool IsValid(object objectInstance
)
94 return IsValid(objectInstance
, RunWhen
.Everytime
);
98 /// Determines whether the specified instance is valid.
100 /// All validators are run for the specified <see cref="RunWhen"/> phase.
103 /// <param name="objectInstance">The object instance to be validated (cannot be null).</param>
104 /// <param name="runWhen">Restrict the set returned to the phase specified</param>
106 /// <see langword="true"/> if the specified instance is valid; otherwise, <see langword="false"/>.
108 public bool IsValid(object objectInstance
, RunWhen runWhen
)
110 if (objectInstance
== null) throw new ArgumentNullException("objectInstance");
114 ErrorSummary summary
= new ErrorSummary();
116 foreach(IValidator validator
in GetValidators(objectInstance
, runWhen
))
118 if (!validator
.IsValid(objectInstance
))
120 summary
.RegisterErrorMessage(validator
.Name
, validator
.ErrorMessage
);
126 errorPerInstance
[objectInstance
] = summary
;
132 /// Gets the registered validators.
134 /// <param name="parentType">Type of the parent.</param>
135 /// <param name="property">The property.</param>
136 /// <returns></returns>
137 public IValidator
[] GetValidators(Type parentType
, PropertyInfo property
)
139 return GetValidators(parentType
, property
, RunWhen
.Everytime
);
143 /// Gets the registered validators.
145 /// <param name="parentType">Type of the parent.</param>
146 /// <param name="property">The property.</param>
147 /// <param name="runWhenPhase">The run when phase.</param>
148 /// <returns></returns>
149 public IValidator
[] GetValidators(Type parentType
, PropertyInfo property
, RunWhen runWhenPhase
)
151 if (parentType
== null) throw new ArgumentNullException("parentType");
152 if (property
== null) throw new ArgumentNullException("property");
154 IValidator
[] validators
= registry
.GetValidators(this, parentType
, property
, runWhenPhase
);
156 if (inferValidators
&& validators
.Length
== 0)
158 Type defaultValidatorForType
= (Type
) type2Validator
[property
.PropertyType
];
160 if (defaultValidatorForType
!= null)
162 validators
= new IValidator
[] { (IValidator) Activator.CreateInstance(defaultValidatorForType) }
;
164 validators
[0].Initialize(property
);
168 Array
.Sort(validators
, ValidatorComparer
.Instance
);
174 /// Gets the error list per instance.
176 /// <param name="instance">The instance.</param>
177 /// <returns></returns>
178 public bool HasErrors(object instance
)
180 ErrorSummary summary
= (ErrorSummary
) errorPerInstance
[instance
];
182 if (summary
== null) return false;
184 return summary
.ErrorsCount
!= 0;
188 /// Gets the error list per instance.
190 /// <param name="instance">The instance.</param>
191 /// <returns></returns>
192 public ErrorSummary
GetErrorSummary(object instance
)
194 return (ErrorSummary
) errorPerInstance
[instance
];
197 private IValidator
[] GetValidators(object objectInstance
, RunWhen runWhen
)
199 if (objectInstance
== null) throw new ArgumentNullException("objectInstance");
201 IValidator
[] validators
= registry
.GetValidators(this, objectInstance
.GetType(), runWhen
);
203 Array
.Sort(validators
, ValidatorComparer
.Instance
);
208 class ValidatorComparer
: IComparer
210 private readonly static ValidatorComparer instance
= new ValidatorComparer();
212 public int Compare(object x
, object y
)
214 IValidator left
= (IValidator
) x
;
215 IValidator right
= (IValidator
) y
;
217 return left
.ExecutionOrder
- right
.ExecutionOrder
;
220 public static ValidatorComparer Instance
222 get { return instance; }