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

C# 向属性访问器添加扩展方法,c#,extension-methods,accessor,C#,Extension Methods,Accessor,我们在视图模型中进行了大量INotifyPropertyChanged实现,坦率地说,出于不便和美观的原因,我们已经厌倦了在代码中显式地触发属性更改事件 我想在属性的setter上添加一个扩展,使生成的代码如下所示: public string LazyAccessor { get; set.notify(); } 有办法做到这一点吗?如果没有,我们能发明一个吗 面向方面编程可以解决您的问题 看。 这里有一些例子: 您的“set.notify()”可以使用一些反射,但我认为这不是一个好

我们在视图模型中进行了大量INotifyPropertyChanged实现,坦率地说,出于不便和美观的原因,我们已经厌倦了在代码中显式地触发属性更改事件

我想在属性的setter上添加一个扩展,使生成的代码如下所示:

public string LazyAccessor
{
  get;
  set.notify();
}

有办法做到这一点吗?如果没有,我们能发明一个吗

面向方面编程可以解决您的问题

看。 这里有一些例子:

您的“set.notify()”可以使用一些反射,但我认为这不是一个好的解决方案,您仍然需要实现getter和setter。

只能添加到类型中。自动属性上的getter和setter由编译器转换为带有支持变量的方法,因此无法对它们使用扩展方法

有办法做到这一点吗

不,没有,不像你贴的那样。扩展方法操作类型,而不是getter或setter

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

这需要对C#规范进行修改——这不太可能发生


您还可以采取其他方法来缓解这一问题,例如,使用基类和方法来为您调用boiler plate。

它们没有进入4.0,但谣传已包含在5.0中

我发现这种方法很有用。

请查看。这将在生成过程中修改代码,使属性实现
INotifyPropertyChanged
模式


这可以作为

使用,但不能在电视机上进行。这是一种行动。但是,您可以这样做:

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返回该类型。

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

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();
    }
}
公共结构列
{
私有TType_值;
私有列(TType值):this()
{
_价值=价值;
}
专用无效集(t类型值)
{
//实现您的自定义设置行为。。。
}
私有TType Get()
{
//实现您的自定义获取行为。。。
返回_值;
}
公共重写字符串ToString()
{
返回_value.ToString();
}
公共静态隐式运算符列(TType p)
{
列=新列(p);
柱集(p);
返回列;
}
公共静态隐式运算符TType(p列)
{
返回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!";
    }
}
公共类测试
{
公共专栏kKey;
公共栏目资金;
公共栏目价值;
公开考试()
{
kKey=42;
dMoney=3.1415926f;
cValue=“愿原力与你同在!”;
}
}

…我知道,这个问题已经过时了,但它可能会对将来的人有所帮助。

另一个有趣的方法。你能看看我的答案,看看这是否可行吗?我珍视你的意见,因为你的声誉高于你。也许它太重了?我想这可能是AOP的前身,比如PostSharp,或者他们不知道PostSharp的存在?@BigM我不太确定这两种方法的具体工作原理。我知道他们都使用IL编织,所以他们在概念上是相似的。我使用NotifyPropertyWeaver的原因是您不需要用属性来混乱您的代码。使用该解决方案是一个很好的理由。PostSharp非常通用,适合解决一个痛点,它肯定会更加简洁@卡德雷尔10我看了看波斯夏普,发现它不够好。这是我的推理,我不确定,但我认为要启动NotifyPropertyEvent,您需要知道原始对象(发送者)和属性名称(本示例中的“LazyAccessor”)。因此,您的代码将使其更加健谈。您将拥有原始对象。。。它将是NotifyAccessorSet函数中的“值”。无论如何。。。只是一个建议。这种方法将实现一个额外的函数调用,这将提供一种在set方法中实现通知的方法。