Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取作为lambda表达式传递的参数的PropertyInfo_C#_.net - Fatal编程技术网

C# 获取作为lambda表达式传递的参数的PropertyInfo

C# 获取作为lambda表达式传递的参数的PropertyInfo,c#,.net,C#,.net,例如,我有一个类: public class Person { public int Id; public string Name, Address; } 我想调用一个方法,根据Id更新此类中的信息: update(myId, myPerson => myPerson.Name = "abc"); 解释:此方法将从数据库中查询并获取给定myId的Person实体,然后将Name设置为“abc”,因此它的工作与我所说的相同: update(myId, myPerson =>

例如,我有一个类:

public class Person
{
  public int Id;
  public string Name, Address;
}
我想调用一个方法,根据Id更新此类中的信息:

update(myId, myPerson => myPerson.Name = "abc");
解释:此方法将从数据库中查询并获取给定myId
Person
实体,然后将
Name
设置为“abc”,因此它的工作与我所说的相同:

update(myId, myPerson => myPerson.Address = "my address");

可能吗?如果是,怎么做?

这是可能的,并且不需要使用
PropertyInfo

您可以这样设计您的方法:

public bool Update<T>(int id, Action<T> updateMethod)
    // where T  : SomeDbEntityType
{
    T entity = LoadFromDatabase(id); // Load your "person" or whatever

    if (entity == null) 
        return false; // If you want to support fails this way, etc...

    // Calls the method on the person
    updateMethod(entity);

    SaveEntity(entity); // Do whatever you need to persist the values

    return true;
}
public bool更新(int-id,Action-updateMethod)
//其中T:SomeDbEntityType
{
T entity=LoadFromDatabase(id);//加载您的“person”或其他内容
if(实体==null)
return false;//如果要支持,则以这种方式失败,等等。。。
//对此人调用该方法
更新方法(实体);
SaveEntity(entity);//执行任何需要持久化值的操作
返回true;
}

我不会使用
PropertyInfo
,就像
Reed Copsey
在他的回答中所说的那样,但仅供参考,您可以使用以下方法提取表达式的
PropertyInfo

public PropertyInfo GetPropertyFromExpression<T>(Expression<Func<T, object>> GetPropertyLambda)
{
    MemberExpression Exp = null;

    //this line is necessary, because sometimes the expression comes in as Convert(originalexpression)
    if (GetPropertyLambda.Body is UnaryExpression)
    {
        var UnExp = (UnaryExpression)GetPropertyLambda.Body;
        if (UnExp.Operand is MemberExpression)
        {
            Exp = (MemberExpression)UnExp.Operand;
        }
        else
            throw new ArgumentException();
    }
    else if (GetPropertyLambda.Body is MemberExpression)
    {
        Exp = (MemberExpression)GetPropertyLambda.Body;
    }
    else
    {
        throw new ArgumentException();
    }

    return (PropertyInfo)Exp.Member;
}

这里是@DanielMöller的答案的一个版本,它针对现代语法进行了更新,并带有指定的异常消息和文档

/// <summary>
///     Gets the corresponding <see cref="PropertyInfo" /> from an <see cref="Expression" />.
/// </summary>
/// <param name="property">The expression that selects the property to get info on.</param>
/// <returns>The property info collected from the expression.</returns>
/// <exception cref="ArgumentNullException">When <paramref name="property" /> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">The expression doesn't indicate a valid property."</exception>
private PropertyInfo GetPropertyInfo<T, P>(Expression<Func<T, P>> property)
{
    if (property == null) {
        throw new ArgumentNullException(nameof(property));
    }

    if (property.Body is UnaryExpression unaryExp) {
        if (unaryExp.Operand is MemberExpression memberExp) {
            return (PropertyInfo)memberExp.Member;
        }
    }
    else if (property.Body is MemberExpression memberExp) {
        return (PropertyInfo)memberExp.Member;
    }

    throw new ArgumentException($"The expression doesn't indicate a valid property. [ {property} ]");
}
//
///从中获取相应的。
/// 
///选择要获取信息的属性的表达式。
///从表达式中收集的属性信息。
///When为空。
///表达式未指示有效的属性。“
私有属性信息GetPropertyInfo(表达式属性)
{
if(属性==null){
抛出新ArgumentNullException(nameof(property));
}
if(property.Body是UnaryExpression-unaryExp){
if(unaryExp.Operand为MemberExpression memberExp){
return(PropertyInfo)memberExp.Member;
}
}
else if(property.Body为MemberExpression memberExp){
return(PropertyInfo)memberExp.Member;
}
抛出新ArgumentException($“表达式未指示有效属性。[{property}]”);
}
甚至更干净的IMHO(另一个变体在@DanielMöller的帖子上)

//
///从中获取相应的。
/// 
///选择要获取信息的属性的表达式。
///从表达式中收集的属性信息。
///When为空。
///表达式未指示有效的属性。“
公共静态属性信息GetPropertyInfo(此表达式)
{
开关(表达式?.Body){
大小写为空:
抛出新ArgumentNullException(nameof(expression));
当unaryExp.Operator为MemberExpression memberExp时的大小写UnaryExpression unaryExp:
return(PropertyInfo)memberExp.Member;
案例MemberExpression memberExp:
return(PropertyInfo)memberExp.Member;
违约:
抛出新ArgumentException($“表达式未指示有效属性。[{expression}]”);
}
}

更正:ArgumentException中有一个拼写错误(应该是ArgumentException)。。。Sub从未使用过。但还是很酷的东西!:)很好的解决方案,但是不必要的强制转换,不必要的嵌套if语句,以及对方法变量使用pascal case,都让我的眼睛流血。我认为应该是一些注释来改进答案。没有不同的答案。
/// <summary>
///     Gets the corresponding <see cref="PropertyInfo" /> from an <see cref="Expression" />.
/// </summary>
/// <param name="property">The expression that selects the property to get info on.</param>
/// <returns>The property info collected from the expression.</returns>
/// <exception cref="ArgumentNullException">When <paramref name="property" /> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">The expression doesn't indicate a valid property."</exception>
private PropertyInfo GetPropertyInfo<T, P>(Expression<Func<T, P>> property)
{
    if (property == null) {
        throw new ArgumentNullException(nameof(property));
    }

    if (property.Body is UnaryExpression unaryExp) {
        if (unaryExp.Operand is MemberExpression memberExp) {
            return (PropertyInfo)memberExp.Member;
        }
    }
    else if (property.Body is MemberExpression memberExp) {
        return (PropertyInfo)memberExp.Member;
    }

    throw new ArgumentException($"The expression doesn't indicate a valid property. [ {property} ]");
}
        /// <summary>
        ///     Gets the corresponding <see cref="PropertyInfo" /> from an <see cref="Expression" />.
        /// </summary>
        /// <param name="expression">The expression that selects the property to get info on.</param>
        /// <returns>The property info collected from the expression.</returns>
        /// <exception cref="ArgumentNullException">When <paramref name="expression" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">The expression doesn't indicate a valid property."</exception>
        public static PropertyInfo GetPropertyInfo<T>(this Expression<Func<T, object>> expression)
        {
            switch (expression?.Body) {
                case null:
                    throw new ArgumentNullException(nameof(expression));
                case UnaryExpression unaryExp when unaryExp.Operand is MemberExpression memberExp:
                    return (PropertyInfo)memberExp.Member;
                case MemberExpression memberExp:
                    return (PropertyInfo)memberExp.Member;
                default:
                    throw new ArgumentException($"The expression doesn't indicate a valid property. [ {expression} ]");
            }
        }