tag a couple of obsolete members
[mcs.git] / class / System.ComponentModel.DataAnnotations / System.ComponentModel.DataAnnotations / ValidationAttribute.cs
blob45e96d656276a053242726b1f371b048b0f0d0fe
1 //
2 // ValidationAttribute.cs
3 //
4 // Authors:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 // Marek Habersack <mhabersack@novell.com>
7 //
8 // Copyright (C) 2008-2010 Novell Inc. http://novell.com
9 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System;
32 using System.ComponentModel;
33 using System.Reflection;
35 namespace System.ComponentModel.DataAnnotations
37 public abstract class ValidationAttribute : Attribute
39 const string DEFAULT_ERROR_MESSAGE = "The field {0} is invalid.";
40 #if !NET_4_0
41 string errorMessage;
42 string errorMessageResourceName;
43 string errorMessageString;
44 Type errorMessageResourceType;
45 #endif
46 string fallbackErrorMessage;
47 Func <string> errorMessageAccessor;
49 protected ValidationAttribute ()
53 protected ValidationAttribute (Func<string> errorMessageAccessor)
55 this.errorMessageAccessor = errorMessageAccessor;
58 protected ValidationAttribute (string errorMessage)
60 fallbackErrorMessage = errorMessage;
63 public virtual string FormatErrorMessage (string name)
65 return String.Format (ErrorMessageString, name);
67 #if NET_4_0
68 public string ErrorMessage { get; set; }
69 public string ErrorMessageResourceName { get; set; }
70 public Type ErrorMessageResourceType { get; set; }
71 #else
72 public string ErrorMessage {
73 get { return errorMessage; }
75 set {
76 if (errorMessage != null)
77 throw new InvalidOperationException ("This property can be set only once.");
79 if (String.IsNullOrEmpty (value))
80 throw new ArgumentException ("Value cannot be null or empty.", "value");
82 if (errorMessageResourceName != null || errorMessageResourceType != null)
83 throw new InvalidOperationException ("This property cannot be set because the attribute is already in the resource mode.");
85 errorMessage = value;
89 public string ErrorMessageResourceName {
90 get { return errorMessageResourceName; }
92 set {
93 if (errorMessageResourceName != null)
94 throw new InvalidOperationException ("This property can be set only once.");
96 if (String.IsNullOrEmpty (value))
97 throw new ArgumentException ("Value cannot be null or empty.", "value");
99 errorMessageResourceName = value;
100 if (errorMessageResourceType != null)
101 errorMessageString = GetStringFromResourceAccessor ();
105 public Type ErrorMessageResourceType {
106 get { return errorMessageResourceType; }
107 set {
108 errorMessageResourceType = value;
109 if (!String.IsNullOrEmpty (errorMessageResourceName))
110 errorMessageString = GetStringFromResourceAccessor ();
113 #endif
114 protected string ErrorMessageString {
115 get {
116 #if NET_4_0
117 return GetStringFromResourceAccessor ();
118 #else
119 return errorMessageString;
120 #endif
123 #if NET_4_0
124 public virtual bool IsValid (object value)
126 throw new NotImplementedException ("IsValid(object value) has not been implemented by this class. The preferred entry point is GetValidationResult() and classes should override IsValid(object value, ValidationContext context).");
129 protected virtual ValidationResult IsValid (object value, ValidationContext validationContext)
131 // .NET emulation
132 if (validationContext == null)
133 throw new NullReferenceException (".NET emulation.");
135 if (!IsValid (value)) {
136 string memberName = validationContext.MemberName;
137 return new ValidationResult (FormatErrorMessage (validationContext.DisplayName), memberName != null ? new string[] { memberName } : new string[] {});
140 return ValidationResult.Success;
142 #else
143 public abstract bool IsValid (object value);
144 #endif
146 #if NET_4_0
147 public ValidationResult GetValidationResult (object value, ValidationContext validationContext)
149 if (validationContext == null)
150 throw new ArgumentNullException ("validationContext");
152 ValidationResult ret = IsValid (value, validationContext);
153 if (ret != null && String.IsNullOrEmpty (ret.ErrorMessage))
154 ret.ErrorMessage = FormatErrorMessage (validationContext.DisplayName);
156 return ret;
158 #endif
159 string GetStringFromResourceAccessor ()
161 string resourceName = ErrorMessageResourceName;
162 Type resourceType = ErrorMessageResourceType;
163 string errorMessage = ErrorMessage;
165 if (resourceName != null && errorMessage != null)
166 throw new InvalidOperationException ("Either ErrorMessage or ErrorMessageResourceName must be set, but not both.");
168 if (resourceType == null ^ resourceName == null)
169 throw new InvalidOperationException ("Both ErrorMessageResourceType and ErrorMessageResourceName must be set on this attribute.");
171 if (errorMessageAccessor != null)
172 return errorMessageAccessor ();
174 if (resourceType != null) {
175 PropertyInfo pi = resourceType.GetProperty (resourceName, BindingFlags.Public | BindingFlags.Static);
176 if (pi == null || !pi.CanRead)
177 throw new InvalidOperationException (
178 String.Format ("Resource type '{0}' does not have an accessible static property named '{1}'.",
179 resourceType, resourceName)
182 if (pi.PropertyType != typeof (string))
183 throw new InvalidOperationException (
184 String.Format ("The property '{0}' on resource type '{1}' is not a string type.",
185 resourceName, resourceType)
188 return pi.GetValue (null, null) as string;
191 if (errorMessage == null)
192 if (fallbackErrorMessage != null)
193 return fallbackErrorMessage;
194 else
195 return DEFAULT_ERROR_MESSAGE;
197 return errorMessage;
199 #if NET_4_0
200 public void Validate (object value, ValidationContext validationContext)
202 if (validationContext == null)
203 throw new ArgumentNullException ("validationContext");
205 ValidationResult result = IsValid (value, validationContext);
206 if (result != null) {
207 string message = result.ErrorMessage;
208 if (message == null)
209 message = FormatErrorMessage (validationContext.DisplayName);
211 throw new ValidationException (message, this, value);
214 #endif
215 public void Validate (object value, string name)
217 if (!IsValid (value))
218 throw new ValidationException (FormatErrorMessage (name), this, value);