是否可以完成此方法?是否可以在最新版本的C#中使用?将此视为DSL,以配置系统以查看某些对象的某些属性更改。
List<string> list = GetProps<AccountOwner>(x => new object[] {x.AccountOwnerName, x.AccountOwnerNumber});
// would return "AccountOwnerName" and "AccountOwnerNumber"
public List<string> GetProps<T>(Expression<Func<T, object[]>> exp)
{
// code here
}
答案 0 :(得分:5)
在C#6中,您将使用:
List<string> list = new List<string>
{
nameof(AccountOwner.AccountOwnerName),
nameof(AccountOwner.AccountOwnerNumber)
};
在此之前,您当然可以将表达式树分开 - 最简单的方法是如何使用表达式树可视化工具,或者使用您已获得的代码并在方法中设置断点(只是让它现在返回null)并检查调试器中的表达式树。我确信它不会非常复杂 - 由于数组而比正常情况多一点。
如果你使用:
,你可以使用匿名类型简化它List<string> list = Properties<AccountOwner>.GetNames(x => new {x.AccountOwnerName, x.AccountOwnerNumber});
然后你可以:
public static class Properties<TSource>
{
public static List<string> GetNames<TResult>(Func<TSource, TResult> ignored)
{
// Use normal reflection to get the properties
}
}
如果您不关心订购,可以使用
return typeof(TResult).GetProperties().Select(p => p.Name).ToList();
如果你做关心排序,你需要查看C#编译器给构造函数参数赋予的名称 - 它有点难看。请注意,我们不需要表达式树 - 我们只需要匿名类型的属性名称。 (诚然,表达树也可以正常工作。)
答案 1 :(得分:2)
如果没有c#6和nameof,您可以从表达式树中获取属性名称,如:
using System.Linq.Expressions;
//...
static string GetNameOf<T>(Expression<Func<T>> property)
{
return (property.Body as MemberExpression).Member.Name;
}
使用它像:
GetNameOf(() => myObject.Property);
不能直接用于对象数组,但是你可以重载一个表达式数组......例如:
static string[] GetNameOf(IEnumerable<Expression<Func<object>>> properties)
{
return properties.Select(GetNameOf).ToArray();
}
并像
一样使用它GetNameOf(
new Expression<Func<object>>[]
{
() => x.AccountOwnerName,
() => x.AccountOwnerNumber
}
);
展示小提琴:https://dotnetfiddle.net/GsV96t
如果您选择这条路线,则单个属性的原始GetNameOf
不会适用于值类型(因为它们在object
中被加到Expression
,现在表达式在内部使用Convert
。通过将代码更改为:
static string GetNameOf<T>(Expression<Func<T>> property)
{
var unary = property.Body as UnaryExpression;
if (unary != null)
return (unary.Operand as MemberExpression).Member.Name;
return (property.Body as MemberExpression).Member.Name;
}
更新了小提琴:https://dotnetfiddle.net/ToXRuu
注意:在这个更新过的小提琴中,我还更新了重载方法以返回List
而不是数组,因为原始代码上有什么