【发布时间】:2016-04-18 19:15:53
【问题描述】:
如何让一个属性中的一个Attribute知道另一个属性的存在?
假设我有这门课,还有很多其他的:
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() 会这样做,给我们一个更改的属性数组,on具有该属性的任何属性:
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")] 传递,因为这样如果将来有人更改类,具体来说就是属性名称,编译时不会抛出任何错误通过它,仅在运行时发生错误,当对该字段进行“编辑”时。或者它可能不会做任何事情,因为它找不到该属性。
知道如何不使用强类型字符串作为属性名称吗?
【问题讨论】:
-
可以使用 Visual Studio 2015 吗?如果是这样,请使用nameof operator.
-
我使用的是 VS 2013。不是我的电脑,无法安装。
-
也将一个属性附加到另一个属性,并使用唯一的字符串链接它们,该字符串除了链接两个属性之外没有其他用途。您必须在属性中使用常量表达式,所以除了您说不能使用的新
nameof运算符之外,没有其他办法。
标签: c# properties custom-attributes