2008-09-15 55 views
5

C#的属性我有一个类与一群看起来像这样的属性:与重复的代码

public string Name 
{ 
    get { return _name; } 
    set { IsDirty = true; _name = value; } 
} 

这将是一个容易得多,如果我可以依靠C#3.0产生这些后备存储,但是有什么办法可以将IsDirty = true;这样我可以写我的属性是这样,仍然可以得到相同的行为:

[MakesDirty] 
public string Name { get; set; } 
+0

看起来这是不可能的(感谢Gishu),所以我将使用CodeRush的模板。感谢您提醒我关于片段。 – 2008-09-15 15:15:52

回答

5

不是没有写出比原始版本更多的(奥术?)代码(您必须使用反射来检查属性上的属性,以及我没有提到它是'较慢')..这是我可以忍受的那种重复。

MS对raising events when a property is changed的需求相同。 INotifyPropertyChanged是变更通知的重要接口。我见过的 每实现不

set 
{ 
    _name = value; 
    NotifyPropertyChanged("Name"); 
} 

如果有可能,我想弄清楚在MS那些聪明的家伙就已经有类似的东西在地方..

3

你可以尝试建立一个代码段可以很容易地创建这些。

0

另一种替代方案可能是codemith等代码生成器来自动创建属性。如果您创建的属性是数据库表中的列,这将特别有用。

0

ContextBound对象。如果您创建了一个扩展上下文绑定对象的类并创建了一个context属性,则可以拦截对此属性所做的调用并设置IsDirty。 .NET将为你的类创建一个代理,所有的调用都会像远程接收器一样。

虽然这种方法的问题是您的代理只会在外部调用时被调用。我会给你一个例子。

A级 {Foo] public int Property1 {get;设置;} public int Property2 {get {return variable;} set {Property1 = value;变量=值; }

}

当property1从另一个类调用,您的代理会如果其他类调用property2,即使集property2的将调用property1没有代理将被调用,(代理invoked.But当你在课堂上时,不是必需的)。

这里有很多使用contextboundobjects的示例代码,请看它。

+0

埃米尔,这在技术上是一个解决方案 - 但是,个人认为这不是一个好的地方来应用这个:)好的答案 - 但不能在这个问题的上下文中upvote。对不起,这个双关语:) – Gishu 2008-09-15 15:03:35

0

我可以推荐使用Enterprise Library为了这个目的。例如,当您输入/退出方法时,策略应用程序块会提供基础结构以执行“某些事情”(某些事情=您可以自己编写代码)。您可以使用属性来控制行为。以此作为提示,详细说明企业库的文档。

0

有一个DefaultValueAttribute可以分配给一个属性,这主要是由设计器工具使用的,所以它们可以指示属性何时被更改,但是,它可能是一种“整齐”的方式来描述默认值对于一个财产是,因此能够确定它是否发生了变化。

您需要使用Reflection来识别属性更改 - 实际上并不是昂贵,除非您正在做很多!

警告:您将无法判断某个属性是否已从非默认值更改回默认值。

2

不,您使用自动属性时,您无法控制实现。最好的选择是使用模板工具,代码片段或创建一个封装了setter逻辑的私有SetValue>(ref T backingField,T value)。

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); 
    } 
} 
+0

但是,你必须在每个这样的类中重复SetValue 方法。如果你把它变成一个公共的静态/实用方法,你必须公开IsDirty状态..不是很酷:) – Gishu 2008-09-15 15:06:09

+0

@Gishu:是的,你会在每个属性和每个类中重复SetValue的调用。取决于你的calsses派生的方式将决定SetValue(因此IsDirty)是否公开。 – 2008-09-15 15:18:29

0

我想说,解决这个问题的最好方法是使用面向方面编程(AOP)。席勒贺兰德做了write up on this on InfoQ。文章有点混乱,但可以遵循。 有很多不同的产品在.NET空间中执行AOP,我推荐PostSharp。

0

如果你确实使用了属性,我相当肯定你必须通过roll your own logic来推断它们的含义以及如何处理它们。无论使用自定义类对象,都必须有一种方法来执行这些属性操作/检查,最好是在实例化时。

否则,你正在寻找使用可能的事件。您仍然必须将该事件添加到每个设置的方法中,但是这样做的好处是您不需要对每个属性上的脏集进行硬编码,并且可以在一个位置控制要执行的操作。这至少会引入更多的代码重用。

3

如果您真的想这样做,要修改代码使用属性所做的工作,有一些方法可以实现,它们都与AOP(面向方面​​编程)相关。查看PostSharp,这是一个后编译器,可以在编译后步骤中修改您的代码。例如,您可以为属性设置一个自定义属性(或方面,它是如何在AOP中调用的),它将属性设置器中的代码注入,将对象标记为脏。如果你想要一些如何实现的例子,你可以看看他们的tutorials

但是要小心使用AOP,因为使用它可能会很容易地产生更多的问题,如果您没有正确使用它,您就试图解决这个问题。

还有更多的AOP框架使用后编译和一些在.Net中使用的方法拦截机制,后者与第一个相比有一些性能上的缺陷。