2016-01-13 75 views
0

如何让一个属性中的属性知道另一个属性的存在?如何让属性'A'中的属性知道属性'B'的存在?

可以说我有这个类,像这样,许多人:

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 diferent,MyPropertyUtils.GetPropertiesIfDirty()做到这一点,让我们改变propertys的阵列,与该属性的任何属性:

PropertyInfo[] MyPropertyUtils.GetPropertiesIfDirty(SomeBaseObject ObjectFromDB, SomeBaseObject NewValues); 

完美。

因此,可以说A已更改,在这种情况下Info包含我们需要的一些信息(在另一个类中可能是任何其他属性)。如果我们想'A'我们只是做property.GetValue(NewValues, null);

但是我们不想'A的价值,我们想'A'或CheckDirty告诉我们在哪里阅读我们想要的一些数据。我如何告诉我的属性CheckDirty从哪里获取值?

我在考虑给出CheckDirty的表达式,但是Attribute的参数“必须是常量表达式,属性参数类型的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 

我们不想通过proprety的名称作为String saing [CheckDirty("Info")]因为这样,如果有人在将来改变类,并在具体的适当ty的名字,编译时就不会抛出错误,只会在运行时发生错误,当编辑该字段时会发生。或者,也许它不会做任何事情,因为它找不到该财产。

任何想法如何不使用强类型字符串作为属性名称?

+2

你可以使用Visual Studio 2015吗?如果是这样,请使用[nameof运算符。](https://msdn.microsoft.com/en-us/library/dn986596.aspx) –

+0

我正在使用VS 2013.不是我的电脑,无法安装的东西。 –

+0

将一个属性附加到另一个属性,并使用唯一的字符串进行链接,除了链接这两个属性之外,它没有任何用途。您必须在属性中使用常量表达式,所以除了您称之为不能使用的新'nameof'运算符之外,没有办法执行此操作。 –

回答

1

你可以使用这样的事情,首先声明,将通过每一个类实现一个接口,需要脏检查:

interface IDirtyCheckPropertiesProvider { 
    string GetPropertyName(string dirtyProperty); 
} 

然后实现它这样

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; 
    } 
} 

在类,将负责处理脏检查,您必须使用此界面来获取目标属性名称。 有一些样板太多,可能会通过使用Reflection API进一步删除。

另一方面,使用属性名称字符串看起来像更简单的解决方案。如果您使用像Resharper这样的工具 - 使用字符串是一个可行的选项 - 当您更改属性名称时,Resharper会自动重构字符串。 也很长一段时间string'ed属性名称用于实现WPF INotifyPropertyChanged。

由于意见建议nameof是VS2015中的最佳选择。

+0

谢谢。把它适应我的情况后,它就像一个魅力。 –

相关问题