题
我有一个类,其中包含许多如下所示的属性:
public string Name
{
get { return _name; }
set { IsDirty = true; _name = value; }
}
如果我可以依靠 C# 3.0 为这些生成后备存储,那就容易多了,但是有什么方法可以分解 IsDirty=true; 吗?这样我就可以像这样编写我的属性并且仍然得到相同的行为:
[MakesDirty]
public string Name { get; set; }
解决方案
不。并非没有编写比原始版本更多(神秘?)的代码 (您必须使用反射来检查属性上的属性以及其他属性。.我有没有提到它“慢”)..这是我可以忍受的重复。
MS也有同样的需求 属性更改时引发事件. 。INotifyPropertyChanged 是更改通知的重要接口。我见过的每个实施
set
{
_name = value;
NotifyPropertyChanged("Name");
}
如果可能的话,我想 MS 的那些聪明人应该已经有了类似的东西了。
其他提示
您可以尝试设置一个代码片段以方便创建这些代码。
不,当您使用自动属性时,您对实现没有任何控制权。最好的选择是使用模板工具、代码片段或创建私有 SetValue<T
>(ref T backingField, T value) 封装了 setter 逻辑。
private void SetValue<T>(ref T backingField, T value)
{
if (backingField != value)
{
backingField = value;
IsDirty = true;
}
}
public string Name
{
get
{
return _name;
}
set
{
SetValue(ref _name, value);
}
}
另一种选择可能是使用代码生成器(例如 Codesmith)来自动创建属性。如果您要创建的属性是数据库表中的列,这将特别有用
我可以推荐使用 企业库 为了这个目的。例如,每当您进入/退出一个方法时,策略应用程序块都会提供基础设施来执行“某事”(某事=您可以自己编写代码)。您可以使用属性来控制行为。以此为提示,详细了解企业库的文档。
有一个可以分配给属性的 DefaultValueAttribute,这主要由设计器工具使用,以便它们可以指示属性何时更改,但是,它可能是描述属性默认值的“简洁”方式,从而能够识别它是否已更改。
您需要使用反射来识别属性更改 - 这实际上不是 那 除非你做很多,否则很贵!
警告:您将无法判断属性是否已从非默认值更改回默认值。
我想说解决这个问题的最好方法是使用面向方面编程(AOP)。马茨·赫兰德做了一个 在 InfoQ 上写下这个. 。文章有点乱,不过还是可以看懂的。在 .NET 领域有许多不同的产品可以执行 AOP,我推荐 PostSharp。
如果你确实选择属性,我相当肯定你必须这样做 滚动你自己的逻辑 推断出它们的含义以及如何处理它们。无论使用自定义类对象,都必须有一种执行这些属性操作/检查的方法,最好是在实例化时。
否则,您正在考虑使用 Maybe 事件。您仍然需要将事件添加到每个 set 方法中,但这样做的好处是您不必硬编码如何处理每个属性上的脏集,并且可以在一个地方控制要做什么。这至少会引入更多的代码重用。
ContextBound 对象。如果您创建一个扩展上下文绑定对象的类并创建一个 ContextAttribute,您可以拦截对此类属性的调用并设置 IsDirty。.NET 将为您的类创建一个代理,以便所有调用都通过类似远程接收器的东西。
但这种方法的问题是,只有在外部调用时才会调用您的代理。我给你举个例子。
class A
{
[Foo]
public int Property1{get; set;}
public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}
当从另一个类调用 property1 时,将调用您的代理。但是,如果另一个类调用 property2,即使 property2 的集合将调用 property1,也不会调用代理(当您在类本身中时,不需要代理)。
有很多使用 ContextBoundObjects 的示例代码,请查看。