Fixing an issue where setting a custom property on a handler will not propagate it...
[castle.git] / Components / General / Validator / Castle.Components.Validator / Validators / AbstractValidator.cs
blob751775ec4326099c0bef4fed987a078774357fc6
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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
17 using System;
18 using System.Collections;
19 using System.Reflection;
21 /// <summary>
22 /// Abstract <see cref="IValidator"/> implementation
23 /// </summary>
24 [Serializable]
25 public abstract class AbstractValidator : IValidator
27 private int executionOrder;
28 private string errorMessage, friendlyName;
29 private PropertyInfo property;
30 private RunWhen runWhen;
31 private IValidatorRegistry validationRegistry;
33 /// <summary>
34 /// Implementors should perform any initialization logic
35 /// </summary>
36 /// <param name="validationRegistry"></param>
37 /// <param name="property">The target property</param>
38 public virtual void Initialize(IValidatorRegistry validationRegistry, PropertyInfo property)
40 this.property = property;
41 this.validationRegistry = validationRegistry;
42 if (errorMessage == null)
44 errorMessage = BuildErrorMessage();
48 /// <summary>
49 /// Obtains the value of a property or field on a specific instance.
50 /// </summary>
51 /// <param name="instance">The instance to inspect.</param>
52 /// <param name="fieldOrPropertyName">The name of the field or property to inspect.</param>
53 /// <returns></returns>
54 public object GetFieldOrPropertyValue(object instance, string fieldOrPropertyName)
56 const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public;
57 Type targetType = instance.GetType();
59 PropertyInfo pi = targetType.GetProperty(fieldOrPropertyName, flags);
61 if (pi == null)
63 FieldInfo fi = targetType.GetField(fieldOrPropertyName, flags);
65 if (fi != null)
67 return fi.GetValue(instance);
70 else
72 return pi.GetValue(instance, null);
75 throw new ValidationException("No public instance field or property named " + fieldOrPropertyName + " for type " +
76 targetType.FullName);
79 /// <summary>
80 /// Gets or sets the validation execution order.
81 /// </summary>
82 /// <value>The execution order.</value>
83 public int ExecutionOrder
85 get { return executionOrder; }
86 set { executionOrder = value; }
89 /// <summary>
90 /// Defines when to run the validation.
91 /// Defaults to <c>RunWhen.Everytime</c>
92 /// </summary>
93 public RunWhen RunWhen
95 get { return runWhen; }
96 set { runWhen = value; }
99 /// <summary>
100 /// The target property
101 /// </summary>
102 public PropertyInfo Property
104 get { return property; }
107 /// <summary>
108 /// The error message to be displayed if the validation fails
109 /// </summary>
110 public String ErrorMessage
112 get { return errorMessage; }
113 set { errorMessage = value; }
116 /// <summary>
117 /// Gets or sets the a friendly name for the target property
118 /// </summary>
119 /// <value>The name.</value>
120 public string FriendlyName
122 get { return friendlyName; }
123 set { friendlyName = value; }
126 /// <summary>
127 /// Gets a value indicating whether this validator supports browser validation.
128 /// </summary>
129 /// <value>
130 /// <see langword="true"/> if browser validation is supported; otherwise, <see langword="false"/>.
131 /// </value>
132 public abstract bool SupportsBrowserValidation { get; }
134 /// <summary>
135 /// Applies the browser validation by setting up one or
136 /// more input rules on <see cref="IBrowserValidationGenerator"/>.
137 /// </summary>
138 /// <param name="config">The config.</param>
139 /// <param name="inputType">Type of the input.</param>
140 /// <param name="generator">The generator.</param>
141 /// <param name="attributes">The attributes.</param>
142 /// <param name="target">The target.</param>
143 public virtual void ApplyBrowserValidation(BrowserValidationConfiguration config,
144 InputElementType inputType, IBrowserValidationGenerator generator,
145 IDictionary attributes, string target)
149 /// <summary>
150 /// Implementors should perform the actual validation upon
151 /// the property value
152 /// </summary>
153 /// <param name="instance">The target type instance</param>
154 /// <returns><c>true</c> if the field is OK</returns>
155 public bool IsValid(object instance)
157 return IsValid(instance, Property.GetValue(instance, null));
160 /// <summary>
161 /// Implementors should perform the actual validation upon
162 /// the property value
163 /// </summary>
164 /// <param name="instance">The target type instance</param>
165 /// <param name="fieldValue">The property/field value. It can be null.</param>
166 /// <returns><c>true</c> if the value is accepted (has passed the validation test)</returns>
167 public abstract bool IsValid(object instance, object fieldValue);
169 /// <summary>
170 /// Builds the error message.
171 /// </summary>
172 protected virtual string BuildErrorMessage()
174 if (!String.IsNullOrEmpty(ErrorMessage))
176 // No localization for now
177 return ErrorMessage;
179 return String.Format(GetString(MessageKey), Name);
182 /// <summary>
183 /// Gets the string from resource
184 /// </summary>
185 /// <param name="key">The key.</param>
186 /// <returns></returns>
187 protected string GetString(string key)
189 return validationRegistry.GetStringFromResource(key);
192 /// <summary>
193 /// Returns the key used to internationalize error messages
194 /// </summary>
195 protected virtual string MessageKey
197 get { return MessageConstants.GenericInvalidField; }
200 /// <summary>
201 /// Gets the property name. The <see cref="FriendlyName"/>
202 /// is returned if non-null, otherwise it will return the property name.
203 /// </summary>
204 public string Name
208 if (friendlyName != null)
210 return friendlyName;
213 return Property.Name;