C# 获取linq表达式中的属性值
我正在尝试使用linq表达式验证MVC代码中的电话号码。代码如下所示:C# 获取linq表达式中的属性值,c#,asp.net-mvc,linq,C#,Asp.net Mvc,Linq,我正在尝试使用linq表达式验证MVC代码中的电话号码。代码如下所示: class Person { public HomePhone { get; set; } } class Employee { public WorkPhone { get; set; } } class Office { Employee Boss { get; set; } } class PersonController : Controller { private static
class Person
{
public HomePhone { get; set; }
}
class Employee
{
public WorkPhone { get; set; }
}
class Office
{
Employee Boss { get; set; }
}
class PersonController : Controller
{
private static ValidatePhoneNumber<M>(Exression<Func<M,string>> propExpr)
{
var member = prop.Body as MemberExpression;
if (member == null)
{
throw new ArgumentException("expression must be a member expression, i.e., x => x.MyProperty");
}
var propInfo = member.Member as PropertyInfo;
if (propInfo == null)
{
throw new ArgumentException("expression is not a property type.");
}
var getter = propExpr.Compile();
string phoneStr = getter(); //this doesn't work
if( !/* ... phoneStr is valid phone number */ )
{
var propName = propInfo.Name;
ModelState[propName] = "invalid format for phone number";
}
}
public ActionResult Create(Person p)
{
ValidatePhoneNumber( p => p.HomePhone );
if( ModelState.IsValid )
....
}
public ActionResult CreatOffice(Office o)
{
ValidatePhoneNumber( o => o.Boss.WorkPhone );
if( ModelState.IsValid )
....
}
}
班级人员
{
公用家庭电话{get;set;}
}
班级员工
{
公用工作电话{get;set;}
}
班级办公室
{
员工上司{get;set;}
}
类PersonController:Controller
{
私有静态ValidatePhoneNumber(Expression PropertExpr)
{
var member=prop.Body作为MemberExpression;
if(成员==null)
{
抛出新ArgumentException(“表达式必须是成员表达式,即x=>x.MyProperty”);
}
var propInfo=member.member作为PropertyInfo;
if(propInfo==null)
{
抛出新ArgumentException(“表达式不是属性类型”);
}
var getter=propExpr.Compile();
字符串phoneStr=getter();//这不起作用
如果(!/*…phoneStr是有效的电话号码*/)
{
var propName=propInfo.Name;
ModelState[propName]=“电话号码格式无效”;
}
}
公共行动结果创建(人员p)
{
验证电话号码(p=>p.HomePhone);
if(ModelState.IsValid)
....
}
公共行动办公室(o办公室)
{
ValidatePhoneNumber(o=>o.Boss.WorkPhone);
if(ModelState.IsValid)
....
}
}
我不能完全理解这里需要的语法。我需要做什么才能拥有一个函数,在这个函数中我传入一个成员属性表达式,并可以访问该属性的名称及其值。仅凭反射就可以得到您想要的结果
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
}
}
更可靠的解决方案可能是使用反射和自定义属性的组合
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; }
}
在Create和createOffice方法中声明的p和o与在lambda表达式中声明的p和o不同。事实上,您应该得到一个错误,因为标识符已经存在于当前范围中 我会将您的方法修改为扩展方法。(需要在静态类中定义) 您的用法将被修改为
public ActionResult Create(Person p)
{
p.ValidatePhoneNumber( person => person.HomePhone );
if( ModelState.IsValid )
....
}
我不认为您提供的代码可以编译(不,我不是说
…
)。这是您试图解决问题的实际代码吗?当有这么多方法验证属性时,您为什么要重新发明轮子?
propertyInfo.GetValue(obj, null);
public ActionResult Create(Person p)
{
p.ValidatePhoneNumber( person => person.HomePhone );
if( ModelState.IsValid )
....
}