我想创建一个Handler,它将获取一个lambda表达式并返回传入的属性的名称,以及该属性的值。
以下是一个示例:
class Program
{
static void Main(string[] args) {
var handler = new Handler();
Contact contact = new Contact() { FirstName = "John", LastName = "Travolta" };
handler.DoSomething(x => contact.FirstName);
handler.DoSomething(x => contact.LastName);
}
}
public class Contact {
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Handler {
public void DoSomething(Func<object, object> func) {
//Write the name of the property.
Console.WriteLine(?);
//Write the Value of the property.
Console.WriteLine(?);
}
}
我该怎么做?
答案 0 :(得分:2)
我的库中的一些代码获取属性名称。
在ExpressionUtils.GetPropertyName
Handler.DoSomething
public static class ExpressionUtils
{
/// <summary>
/// Gets the name of any argument given in the lambda expression.
/// Sample:
/// int argument = 10;
/// string name = ExpressionUtils.GetName(() => argument);
/// </summary>
/// <typeparam name="T">Argument type</typeparam>
/// <param name="selector">Selector for the name of the argument</param>
/// <returns>Argument name</returns>
public static string GetName<T>(Expression<Func<T>> selector)
{
if (selector == null)
{
throw new ArgumentNullException("selector");
}
MemberExpression member = RemoveUnary(selector.Body);
if (member == null)
{
throw new InvalidOperationException("Unable to get name from expression.");
}
return member.Member.Name;
}
/// <summary>
/// Gets the name of the property given in the lambda expression.
/// Sample:
/// string propertyName = ExpressionUtils.GetPropertyName(() => x.Property);
/// </summary>
/// <typeparam name="TProperty">Property type</typeparam>
/// <param name="propertySelector">Selector for the name of the property</param>
/// <returns></returns>
public static string GetPropertyName<TProperty>(Expression<Func<TProperty>> propertySelector)
{
return GetPropertyNameImpl(propertySelector);
}
/// <summary>
/// Gets the name of the property given in the lambda expression.
/// Sample:
/// <![CDATA[
/// string propertyName = ExpressionUtils.GetPropertyName<Entity, int>(y => y.Property);
/// ]]>
/// </summary>
/// <typeparam name="TEntity">Entity containing the property type</typeparam>
/// <typeparam name="TProperty">Propety type</typeparam>
/// <param name="propertySelector">Selector for the name of the property</param>
/// <returns></returns>
public static string GetPropertyName<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> propertySelector)
{
return GetPropertyNameImpl(propertySelector);
}
/// <summary>
/// Gets the name of the property given in the lambda expression.
/// Sample:
/// <![CDATA[
/// string propertyName = ExpressionUtils.GetPropertyName<Entity, int>(y => y.Property);
/// ]]>
/// </summary>
/// <typeparam name="TEntity">Entity containing the property type</typeparam>
/// <param name="propertySelector">Selector for the name of the property</param>
/// <returns></returns>
public static string GetPropertyName<TEntity>(Expression<Func<TEntity, object>> propertySelector)
{
return GetPropertyNameImpl(propertySelector);
}
private static string GetPropertyNameImpl(LambdaExpression propertySelector)
{
if (propertySelector == null)
{
throw new ArgumentNullException("propertySelector");
}
MemberExpression member = RemoveUnary(propertySelector.Body);
if (member == null)
{
throw new InvalidOperationException("Expression is not an access expression.");
}
var property = member.Member as PropertyInfo;
if (property == null)
{
throw new InvalidOperationException("Member in expression is not a property.");
}
return member.Member.Name;
}
private static MemberExpression RemoveUnary(Expression toUnwrap)
{
if (toUnwrap is UnaryExpression)
{
return ((UnaryExpression)toUnwrap).Operand as MemberExpression;
}
return toUnwrap as MemberExpression;
}
}
答案 1 :(得分:2)
public void DoSomething<T>(Expression<Func<T, object>> expr, T target) {
var pi = (PropertyInfo)(((MemberExpression)expr.Body).Member);
Console.WriteLine(pi.Name);
//Write the Value of the property.
Console.WriteLine(expr.Compile()(target));
}
您还必须将目标传递给方法:
handler.DoSomething(x => contact.FirstName, x);