Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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# 将类的属性设置为函数的参数_C#_Linq_Lambda_Reflection - Fatal编程技术网

C# 将类的属性设置为函数的参数

C# 将类的属性设置为函数的参数,c#,linq,lambda,reflection,C#,Linq,Lambda,Reflection,我的意图是传递类的公共属性,比如: class MyTestClass { public string Name { get; set; } public DateTime StartedAt { get; set; } public TimeSpan Duration { get; set; } } 对于函数a参数: static void MyCustomFunc(params Expression<Func<MyTestClass, object&g

我的意图是传递类的公共属性,比如:

class MyTestClass
{
    public string Name { get; set; }
    public DateTime  StartedAt { get; set; }
    public TimeSpan Duration { get; set; }
}
对于函数a参数:

static void MyCustomFunc(params Expression<Func<MyTestClass, object>>[] props)
{
    foreach (var p in props)
    {
        // The following only works for Name property, not for StartedAt or Duration
        MemberExpression member = p.Body as MemberExpression;
        PropertyInfo propertyInfo = (PropertyInfo)member.Member;

        string name = propertyInfo.Name;
        Type type = propertyInfo.PropertyType;
        Func<MyTestClass, object> func = p.Compile();
    }
}
产生与以下内容不同的结果:

MyCustomFunc(x => x.StartedAt, x => x.Name);

不同于

MyCustomFunc(x => x.Duration, x => x.StartedAt, x => x.Name);
我的问题是如何让反射工作。由于某种原因,我无法理解p.Body:

对于{x=>x.Name}等于{x.Name},但 对于{x=>x.StartedAt}等于{Convertx.StartedAt} 第一个问题可以由

MemberExpression member = p.Body as MemberExpression;

但是第二个返回null,所以我得到了一个null引用异常。

硬编码类型参数的业务让我有点发痒,所以我改变了这一点。我有种感觉你下一步会搞乱那部分。如果不是这样,请告诉我,我会把它换回来

public static void MyCustomFunc<T>(this T inst, params Expression<Func<T, object>>[] props)
{
    foreach (var p in props)
    {
        PropertyInfo propertyInfo = null;

        //  Because the return type of the lambda is object, when the property is a value 
        //  type, the Expression will have to be a unary expression to box the value. 
        //  The MemberExpression will be the operand from that UnaryExpression. 
        if (p.Body is UnaryExpression ue && ue.Operand is MemberExpression ueMember)
        {
            propertyInfo = (PropertyInfo)ueMember.Member;
        }
        else if (p.Body is MemberExpression member)
        {
            propertyInfo = (PropertyInfo)member.Member;
        }
        else
        {
            throw new ArgumentException("Parameters must be property access expressions " 
                + "in the form x => x.Property");
        }

        string name = propertyInfo.Name;
        Type type = propertyInfo.PropertyType;
        Func<T, object> func = p.Compile();
    }
}

表达式:要传递的lambda返回对象。DateTime是一个结构,因此必须对其进行装箱才能使其成为对象。任何值类型都会发生这种情况。我只想为值类型添加一个特例,然后继续。稍微偏离主题:现在我们在C中有了nameof,我的建议是只使用编译时字符串,并使用nameof x.Duration传递它们,而不是所有运行时表达式的魔力。另请参见:。正如@EdPlunkett所说,DateTime是一个结构,您可以通过member=p实现您想要的功能。Body作为MemberExpression??UnaryExpressionp.Body.Operator作为MemberExpression;相反,如果p.Body是UnaryExpression ue&&ue.Operator是MemberExpression ueMember{propertyInfo=PropertyInfoumber.Member;}否则如果p.Body是MemberExpression成员{…}否则{/*throw*/}我会这样做。相同差异。变量主体=p.主体;如果body是一元表达式ua{body=ua.operator;};var member=body作为MemberExpression;如果member==null{throw…}member.member.Name;这就是我的方法……这正是我所需要的,以表达式的形式传入类Poperties,并通过反射获得它们的PropertyInfo。再次感谢!
MemberExpression member = p.Body as MemberExpression;
public static void MyCustomFunc<T>(this T inst, params Expression<Func<T, object>>[] props)
{
    foreach (var p in props)
    {
        PropertyInfo propertyInfo = null;

        //  Because the return type of the lambda is object, when the property is a value 
        //  type, the Expression will have to be a unary expression to box the value. 
        //  The MemberExpression will be the operand from that UnaryExpression. 
        if (p.Body is UnaryExpression ue && ue.Operand is MemberExpression ueMember)
        {
            propertyInfo = (PropertyInfo)ueMember.Member;
        }
        else if (p.Body is MemberExpression member)
        {
            propertyInfo = (PropertyInfo)member.Member;
        }
        else
        {
            throw new ArgumentException("Parameters must be property access expressions " 
                + "in the form x => x.Property");
        }

        string name = propertyInfo.Name;
        Type type = propertyInfo.PropertyType;
        Func<T, object> func = p.Compile();
    }
}
new MyTestClass { Name = "Stan", StartedAt = DateTime.Now }
    .MyCustomFunc(x => x.Name, x => x.StartedAt);