如何让一个属性中的属性知道另一个属性的存在?
让我说我有这个班级,像这样,还有很多其他人:
public class MyClass
{
[CheckDirty] //a custom attribute (that it is empty for now)
public int A { get; set; }
public int B { get; set; }
public string Description { get; set; }
public string Info { get; set; }
}
在我们程序的某个地方,如果我们想查看对象是否更改了任何CheckDirty
属性的值,例如假设它与DB不同,MyPropertyUtils.GetPropertiesIfDirty()
执行此操作,为我们提供一个数组在具有该属性的任何属性上更改了属性:
PropertyInfo[] MyPropertyUtils.GetPropertiesIfDirty(SomeBaseObject ObjectFromDB, SomeBaseObject NewValues);
完美。
所以,让我们说A
已更改,在这种情况下Info
包含我们需要的一些信息(在另一个类中可能是任何其他属性)。如果我们想要' A'我们只做property.GetValue(NewValues, null);
但我们不想要' A的价值,我们想要' A'或CheckDirty
告诉我们在哪里阅读我们想要的一些数据。如何告诉我的属性CheckDirty
从何处获取值?
我在考虑给CheckDirty
一个表达式,但是一个属性的参数"必须是一个常量表达式,typeof表达式或属性参数类型的数组创建表达式"(那是VS说的)。
所以我决定,"好吧,让我们给它一个字符串,其中包含该属性的名称",所以我的尝试失败了:
(这是我们需要处理的所有代码,其余的只是提供某种上下文示例)
public class CheckDirty : Attribute
{
public String targetPropertyName;
public CheckDirty(String targetPropertyName)
{
this.targetPropertyName = targetPropertyName;
}
}
public class MyClass
{
//Code fails on this line
[CheckDirty(BoundPropertyNames.Info)]
public int Id { get; set; }
public string Info { get; set; }
public static class BoundPropertyNames
{
public static readonly string Info = ((MemberExpression)
((Expression<Func<MyClass, string>>)
(m => m.Info)
).Body
).Member.Name;
}
}
这是我得到的错误:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
我们不希望将该属性的名称作为String
saing [CheckDirty("Info")]
传递,因为如果将来任何人更改该类,并具体使用该属性的名称,编译时不会抛出任何错误,只会在运行时发生错误,当编辑&#34;编辑&#34;到那个领域会发生。或者也许它不会做任何事情,因为它无法找到属性。
知道如何不使用强类型字符串作为属性名称吗?
答案 0 :(得分:1)
您可以使用类似的东西,首先声明一个接口,该接口将由需要进行脏检查的每个类实现:
SELECT IIF(clock_to - clock_at_from < 0,
IIF(12 - (clock_at_from - clock_to) >= 3, 5, 12 - (clock_at_from - clock_to)),
clock_to - clock_at_from) as clock_pos
FROM Conditions
然后像那样实现它
interface IDirtyCheckPropertiesProvider {
string GetPropertyName(string dirtyProperty);
}
在负责处理脏检查的类中,必须使用此接口来获取目标属性名称。 使用Reflection API可以进一步删除有太多的样板。
另一方面,使用字符串作为属性名称看起来更简单的解决方案。如果使用像Resharper这样的工具 - 使用字符串是一个可行的选项 - 当您更改属性名称时,Resharper将自动重构字符串。 同样很长一段时间,字符串的属性名称被用于实现WPF INotifyPropertyChanged。
评论建议class DataEntity : IDirtyCheckPropertiesProvider {
[CheckDirty]
public int Id { get; set; }
public string Info { get; set; }
string GetPropertyName(string dirtyProperty) {
if (GetPropertyNameFromExpression(x => Id) == dirtyProperty)
return GetPropertyNameFromExpression(x => Info);
return null;
}
}
是VS2015的最佳选择。