我的意图是传递一个类的公共属性,例如:
class MyTestClass
{
public string Name { get; set; }
public DateTime StartedAt { get; set; }
public TimeSpan Duration { get; set; }
}
对函数使用参数:
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();
}
}
该函数应该收集此信息并将其提供给导出器类,该类将MyTestClass
对象集导出到CSV文件。
写入CSV文件的输出取决于送入MyCustomFunc
的属性的数量,类型和顺序。
所以这个:
MyCustomFunc(x => x.Name, x => x.StartedAt);
产生与以下结果不同的结果:
MyCustomFunc(x => x.StartedAt, x => x.Name);
和
MyCustomFunc(x => x.StartedAt, x => x.Name, x => x.Duration);
与
不同MyCustomFunc(x => x.Duration, x => x.StartedAt, x => x.Name);
我的问题是使反射起作用。由于某些原因,我无法理解p.Body
:
{x => x.Name}
等于{x.Name}
,但{x => x.StartedAt}
等于{Convert(x.StartedAt)}
第一个可以由
处理MemberExpression member = p.Body as MemberExpression;
但是第二个返回null
,所以我得到一个空引用异常。
答案 0 :(得分:4)
对类型参数进行硬编码的工作使我有点头疼,所以我改变了这一点。我有种感觉,您接下来将要弄混这一部分。让我知道是否不是这种情况,我会改回来。
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);