向属性访问器添加扩展方法

6
我们在 ViewModel 中实现了很多 INotifyPropertyChanged,并且坦白地说,我们已经厌倦了在代码中明确触发属性更改事件,这不仅不方便而且不美观。
我想在属性的 setter 上放置一个扩展,使得最终的代码看起来像:
public string LazyAccessor
{
  get;
  set.notify();
}

有没有一种方法可以做到这一点?如果没有,我们能发明一种吗?

7个回答

4

我理解这是 AOP 的先驱之一,例如 PostSharp 或者他们不知道 PostSharp 的存在? - Mike Perrenoud
@BigM 我不太确定它们的细节是如何工作的。我知道它们都使用IL Weaving,因此在概念上它们是相似的。我使用NotifyPropertyWeaver的原因是你不需要用属性来弄乱你的代码。 - cadrell0
使用该解决方案的好处很多。PostSharp非常通用,而这个解决方案则适用于解决一个痛点,因此一定会更加简洁! - Mike Perrenoud
@cadrell0 我看了一下PostSharp,发现它有些不足。这是我的理由:http://simoncropp.com/attemptingtosolvetheinotifypropertychangedproblem - Simon

3

3

扩展方法只能添加到类型上。自动属性的getter和setter被编译器转换为带有后备变量的方法,因此无法在它们上面放置扩展方法。


2

有没有一种方法可以做到这一点?

不,没有,就像您发布的那样。扩展方法是针对类型而非getter或setter进行操作。

如果没有,我们能发明一个吗?

那需要对C#规范进行更改-这不太可能发生。

还有其他方法可以采取来简化此过程-例如使用具有可为您调用模板代码的方法的基类。


另一种有趣的方法。你能看一下我的答案,看它是否可行吗?我很重视你的意见,因为你的声誉是如此卓著。也许这太繁重了? - Mike Perrenoud

0

你可以通过重载自定义泛型结构体的转换运算符来模拟“类似属性”的行为,而无需手动调用事件。以下是我的解决方案:

public struct column<TType>
{
    private TType _value;

    private column(TType value) : this()
    {
        _value = value;
    }

    private void Set(TType value)
    {
        // Implement your custom set-behavior...
    }

    private TType Get()
    {
        // Implement your custom get-behavior...
        return _value;
    }

    public override string ToString()
    {
        return _value.ToString();
    }

    public static implicit operator column<TType>(TType p)
    {
        column<TType> column = new column<TType>(p);
        column.Set(p);
        return column;
    }

    public static implicit operator TType(column<TType> p)
    {
        return p.Get();
    }
}

我使用泛型参数声明结构体,以避免转换错误。您可以像这样使用它:

public class Test
{
    public column<int> kKey;

    public column<float> dMoney;

    public column<string> cValue;


    public Test()
    {
        kKey   = 42;
        dMoney = 3.1415926f;
        cValue = "May the force be with you!";
    }
}

我知道,这个问题已经过时了,但它可能会在未来帮助到某些人。


0

你不能在集合本身上这样做。那是一个动作。但是你可能可以这样做:

public static class extensions()
{
  public static NotifyAccessorSet(this string value) { some code }
}

public class SomeClass()
{
  .....
  private string mAccessor;

  public string LazyAccessor{
     get { return mAccessor; }
     set { mAccessor = value; mAccessor.NotifyAccessorSet(); }
  }

}

这有点脱离我的思路,记住扩展方法将适用于所有类型的字符串,因此您可能需要实现自己的返回类型并将扩展方法应用于它。然后从lazyaccessor返回该类型。


我不确定,但我认为要触发NotifyPropertyEvent,您需要知道原始对象(发送者)和属性名称(在此示例中为“LazyAccessor”)。因此,您的代码将使其更加啰嗦。 - Ondra
你会有一个初始对象,这个"值"将在NotifyAccessorSet函数中。无论如何,这只是一个建议。这种方法将实现额外的函数调用,这只是提供一种在set方法中实现通知的方式。 - DRobertE

0

它们没有被包含在4.0中,但据说会包含在5.0中。

我发现this的方法很有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接