java
c
xml
ajax
python
mysql
ruby-on-rails
html5
json
perl
facebook
tsql
apache
mvc
php5
asp
jsp
postgresql
dom
You can get what it seems that you want with Reflection alone.
namespace Forums.LinqToValidatePhoneNumberProperty { using System; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; public class PhoneNumberRule { #region Fields static string _usPhonePattern = @"1?\W*([2-9][0-8][0-9])" + @"\W*([2-9][0-9]{2})\W*" + @"([0-9]{4})(\se?x?t?(\d*))?"; static Regex _usPhoneRegex = new Regex( _usPhonePattern ); #endregion Fields #region Methods public static void Validate( object target, string propertyName ) { Type targetType = target.GetType(); PropertyInfo targetProperty = ( from propertyInfo in targetType.GetProperties() where ( propertyInfo.Name == propertyName && propertyInfo.PropertyType.IsAssignableFrom( typeof (string ) ) ) select propertyInfo ).First(); if ( targetProperty == null ) { throw new InvalidOperationException( "No appropriate property " + "could be found on the " + "target object." ); } string testValue = targetProperty.GetValue( target, null ) as string; if ( testValue != null && _usPhoneRegex.IsMatch( testValue ) ) { return; } else { ModelState[propertyName] = "Not a valid phone number format"; } } #endregion Methods } }
A more robust solution might be to use a combination of reflection and custom attributes.
public class PhoneNumberRule { #region Fields static string _usPhonePattern = @"1?\W*([2-9][0-8][0-9])" + @"\W*([2-9][0-9]{2})\W*" + @"([0-9]{4})(\se?x?t?(\d*))?"; static Regex _usPhoneRegex = new Regex( _usPhonePattern ); #endregion Fields #region Methods public static void ValidateProperties( object target ) { Type targetType = target.GetType( ); var phoneNumberProperties = from propertyInfo in targetType.GetProperties( ) where propertyInfo.GetCustomAttributes( typeof( PhoneNumberAttribute ), true ).Length > 0 select propertyInfo; foreach ( PropertyInfo targetProperty in phoneNumberProperties ) { string value = targetProperty.GetValue( target, null) as string; if ( value == null || !_usPhoneRegex.IsMatch( value ) ) { ModelState[ targetProperty.Name ] = "Not a valid phone number format"; } } } } [AttributeUsage(AttributeTargets.Property)] public class PhoneNumberAttribute : Attribute { } public class Person { [PhoneNumber( )] public string HomePhone { get; set; } }
The p and o you declare in the Create and CreatOffice methods are not the same as the p and o you declare in your lambda expression. In fact you should be getting an error because the identifier already exists in the current scope.
I would modify your method to be an extension method. (It will need to be defined in a static class)
public static ValidatePhoneNumber<M>(this M obj, Exression<Func<M,string>> propExpr)
you can then access the property value from 'obj'. Getting the value would be something like...
propertyInfo.GetValue(obj, null);
Your usage would then be modified to...
public ActionResult Create(Person p) { p.ValidatePhoneNumber( person => person.HomePhone ); if( ModelState.IsValid ) .... }