重复代码的c#属性

时间:2008-09-15 14:46:57

标签: c# properties attributes

我有一个包含大量属性的类:

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

如果我可以依靠C#3.0来为这些生成后备存储,那将会容易得多,但有没有办法将IsDirty = true分解出去;这样我就可以像这样编写我的属性并仍然得到相同的行为:

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

10 个答案:

答案 0 :(得分:5)

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

MS对raising events when a property is changed有同样的需求。 INotifyPropertyChanged是变更通知的重要界面。我见过的每一个实现 确实

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

如果有可能的话,我会认为MS的那些聪明人已经有了类似的东西..

答案 1 :(得分:3)

您可以尝试设置代码段,以便轻松创建这些代码段。

答案 2 :(得分:3)

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

但请小心使用AOP,因为如果使用不正确,您可以轻松地使用它来创建更多问题。

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

答案 3 :(得分:2)

不,当您使用自动属性时,您无法控制实施。最好的选择是使用模板工具,代码片段或创建一个私有的SetValue <T&gt;(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);
   }
}

答案 4 :(得分:0)

另一种替代方案可能是代​​码生成器,例如代码生成器,以自动创建属性。如果您要创建的属性是数据库表中的列

,这将特别有用

答案 5 :(得分:0)

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有很多示例代码,请查看它。

答案 6 :(得分:0)

我建议您为此目的使用Enterprise Library。策略应用程序块提供基础结构,以便在您进入/退出方法时执行“某些操作”(某些内容=您可以自行编码)。您可以使用属性控制行为。将其作为一个提示,详细了解企业库的文档。

答案 7 :(得分:0)

有一个可以分配给属性的DefaultValueAttribute,这主要由设计器工具使用,因此它们可以指示属性何时被更改,但是,它可能是一种“整洁”的方式来描述默认值属性是,因此能够识别它是否已经改变。

您需要使用Reflection来识别属性更改 - 除非您正在做很多事情,否则实际上 非常昂贵!

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

答案 8 :(得分:0)

我认为解决这个问题的最佳方法是使用面向方面编程(AOP)。 Mats Helander做了write up on this on InfoQ。这篇文章有点乱,但可以遵循。 有很多不同的产品在.NET领域做AOP,我推荐PostSharp。

答案 9 :(得分:0)

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

否则,您正在考虑使用可能的事件。你仍然需要将事件添加到每个set方法中,但是这样做的好处是你不会硬编码如何处理每个属性上的脏集,并且可以在一个地方控制要做的事情。这至少会引入更多的代码重用。