为了扩展我的评论,这是一种用不同方法完成任务的方法。你说你想“在一个类中指示相关的属性”,并且你“想使用 lambda 表达式,以便我可以将一个强类型传递给我的属性的构造函数,而不是一个“魔术字符串”。这样我可以利用编译器类型检查”。
这是一种指示相关属性的方法,这些属性是编译时类型的并且没有任何魔术字符串:
public class MyClass
{
public int EmployeeId { get; set; }
public int EmployeeNumber { get; set; }
}
这是正在考虑的课程。我们想指出这一点EmployeeId并且EmployeeNumber是相关的。为了代码简洁,让我们把这个类型别名放在代码文件的顶部。这根本没有必要,但它确实使代码不那么令人生畏:
using MyClassPropertyTuple =
System.Tuple<
System.Linq.Expressions.Expression<System.Func<MyClass, object>>,
System.Linq.Expressions.Expression<System.Func<MyClass, object>>
>;
这为两个sMyClassPropertyTuple的 a 创建了一个别名,每个 s 都捕获从 a到对象的函数定义。例如,属性 getter on就是这样的函数。TupleExpressionMyClassMyClass
现在让我们捕捉这种关系。在这里,我在 上创建了一个静态属性MyClass,但是这个列表可以在任何地方定义:
public class MyClass
{
public static List<MyClassPropertyTuple> Relationships
= new List<MyClassPropertyTuple>
{
new MyClassPropertyTuple(c => c.EmployeeId, c => c.EmployeeNumber)
};
}
C# 编译器知道我们正在构造 a Tupleof Expressions,因此我们不需要在这些 lambda 表达式前面进行任何显式转换——它们会自动转换为Expressions。
就定义而言,基本上就是这样 -这些EmployeeId和EmployeeNumber提及在编译时是强类型和强制执行的,并且进行属性重命名的重构工具应该能够在重命名期间找到这些用法(ReSharper 绝对可以)。这里没有魔线。
但当然,我们也希望能够在运行时询问关系(我假设!)。我不确切知道你想怎么做,所以这段代码只是说明性的。
class Program
{
static void Main(string[] args)
{
var propertyInfo1FromReflection = typeof(MyClass).GetProperty("EmployeeId");
var propertyInfo2FromReflection = typeof(MyClass).GetProperty("EmployeeNumber");
var e1 = MyClass.Relationships[0].Item1;
foreach (var relationship in MyClass.Relationships)
{
var body1 = (UnaryExpression)relationship.Item1.Body;
var operand1 = (MemberExpression)body1.Operand;
var propertyInfo1FromExpression = operand1.Member;
var body2 = (UnaryExpression)relationship.Item2.Body;
var operand2 = (MemberExpression)body2.Operand;
var propertyInfo2FromExpression = operand2.Member;
Console.WriteLine(propertyInfo1FromExpression.Name);
Console.WriteLine(propertyInfo2FromExpression.Name);
Console.WriteLine(propertyInfo1FromExpression == propertyInfo1FromReflection);
Console.WriteLine(propertyInfo2FromExpression == propertyInfo2FromReflection);
}
}
}
代码propertyInfo1FromExpression和propertyInfo2FromExpression这里我在调试时明智地使用了 Watch 窗口 - 这通常是我计算Expression树实际包含的内容的方式。
运行这将产生
EmployeeId
EmployeeNumber
True
True
表明我们可以成功提取相关属性的细节,并且(至关重要)它们与PropertyInfo通过其他方式获得的 s参考相同。希望您可以将它与您实际使用的任何方法结合使用,以在运行时指定感兴趣的属性。