具有重复代码的C#属性
我有一类带有一堆属性的类,如下所示:
public string Name { get { return _name; } set { IsDirty = true; _name = value; } }
如果我可以依靠C3.0为其生成后备存储,则容易得多,但是有什么方法可以排除IsDirty = true;这样我就可以像这样编写我的属性,并且仍然获得相同的行为:
[MakesDirty] public string Name { get; 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的示例代码,请仔细研究。
回答
不。不是没有编写比原始版本多得多的代码(arcane?)(我们必须使用反射来检查属性的属性,否则不可以。我可以忍受的那种重复。
当属性更改时,MS同样需要引发事件。 INotifyPropertyChanged是更改通知的重要接口。我见过的每一个实现
做
set { _name = value; NotifyPropertyChanged("Name"); }
如果可能的话,我认为MS的那些聪明人已经有了类似的东西。
回答
我可以建议为此目的使用企业库。例如,当我们输入/退出方法时,Policy Application Block提供了执行"某事"(某事=我们可以自己编写代码)的基础结构。我们可以使用属性控制行为。以此作为提示,详细介绍企业库的文档。
回答
有一个可以分配给属性的DefaultValueAttribute,主要由设计器工具使用,以便它们可以指示何时更改了属性,但是,这可能是一种"简洁"的方式来描述属性的默认值是,从而能够确定它是否已更改。
我们需要使用Reflection来标识属性更改,除非我们进行了大量更改,否则实际上这些更改并不那么昂贵!
警告:我们将无法判断某个属性是否已从非默认值BACK更改为默认值。
回答
不,当我们使用自动属性时,我们对实现没有任何控制。最好的选择是使用模板工具,代码段或者创建一个私有的SetValue<T
>(ref T backingField,T值),它封装了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); } }
回答
我想说,解决此问题的最佳方法是使用面向方面的编程(AOP)。 Mats Helander在InfoQ上对此进行了撰写。这篇文章有点凌乱,但可以遵循。
我建议使用PostSharp,在.NET空间中有许多不同的产品可以进行AOP。
回答
如果我们确实使用了Attributes,我可以肯定地说,我们必须运用自己的逻辑来推断它们的含义以及如何处理它们。无论使用哪种自定义类对象,都必须有一种方法来执行这些属性操作/检查,最好在实例化时执行。
否则,我们正在考虑使用事件。我们仍然必须将事件添加到每个set方法中,但是这样做的好处是我们不必对每个属性上的脏集进行硬编码,并且可以在一处控制要执行的操作。至少,这将导致更多的代码重用。
回答
如果我们真的想这样做,可以使用属性来修改代码的功能,则有一些方法可以实现,它们都与AOP(面向方面的编程)有关。签出PostSharp,这是一个后编译器,可以在之后的编译步骤中修改代码。例如,我们可以为属性(或者方面,在AOP中如何称呼)设置一个自定义属性,以将代码注入属性设置器中,从而将对象标记为脏。如果我们需要一些有关如何实现此目标的示例,则可以查看其教程。
但是请谨慎使用AOP,因为如果使用不当,我们可能会很容易使用它来解决更多问题。
.Net中存在更多的AOP框架,其中一些使用后编译,而某些使用方法拦截机制,.Net中存在,与第一种相比,后者具有一些性能缺陷。