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);