有没有办法拦截C#中的setter和getter?

时间:2011-05-17 12:43:59

标签: c# interceptor getter-setter

在Ruby和PHP(我猜其他语言)中,只要设置了属性,就会调用一些实用程序方法。 (Ruby的 * instance_variable_set * ,PHP的 * __ set * )。

所以,假设我有一个像这样的C#类:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

现在,假设如果调用Person类中的任何属性设置器,我想先调用另一个方法,然后继续使用setter的默认行为,这同样适用于属性setter

这可能吗?


修改 的 我想在没有定义支持字段的情况下这样做。

11 个答案:

答案 0 :(得分:28)

一般情况下;但有几个选择;

  • 继承自ContextBoundObject - 其中 允许此操作,但性能成本
  • 编写显式属性(即带有支持字段),并手动添加实用程序方法调用
  • 查看编译时编织者,例如PostSharp - 通常通过发现属性或类似物
  • 查看运行时代码生成器,由一些DI / IoC工具(以及其他一些“装饰器”工具)提供 - 它们可以装饰或子类化您的对象以添加额外的代码

答案 1 :(得分:14)

可以直接在属性体中进行,但是您需要使用适当的支持字段而不是auto-implemented properties

private string firstName;

public string FirstName 
{ 
  get { return firstName;} 
  set 
  {
    if(check(value))
    {
       firstName = value;
    }
  } 
}

即使使用自动实现的属性,您也会获得一个支持字段 - 这是由编译器生成的,您无法直接访问它。


编辑:

看到你不想要一个支持领域,你还有其他的选择 - 使用像PostSharp这样的AOP工具可以帮助你。

答案 2 :(得分:4)

您必须完整地编写属性才能实现此目的。

答案 3 :(得分:2)

我知道这已经得到了适当的回答,但我会举一个例子向您展示实现您想要的语法:

public class Person
{
    private 
    public string FirstName
    {
        get
        {
            return _firstName;
        }
        set
        {
            // see how we can call a method below? or any code for that matter..
            _firstName = SanitizeName(value);
        }
    }
}

答案 4 :(得分:2)

您是否可以重写您的类来实现接口?如果是这样,Unity's interface interceptor可能会为您提供所需内容。如果接口不是一个选项,那么该链接也会记录Unity的类型和实例拦截器。

答案 5 :(得分:1)

没有开箱即用。您需要手动或自动使用IL重写将代码插入每个属性setter和getter。

如果您想手动执行此操作,则无法再使用自动属性 如果您想自动执行此操作,请查看AOP。

答案 6 :(得分:1)

是的,当然......

在您的示例中,您使用的是自动属性,没有支持字段....您只需要为您的属性创建一个支持字段,然后您就可以在setter和getter中执行您想要的操作。

示例:

private string firstName;

public string FirstName
{
 get { return firstName; }

 set { doMethod(); firstName = value;}
}

答案 7 :(得分:1)

模拟框架可以做到这一点,以及像Unity这样的IoC库。执行此类操作的唯一方法是使用IL重写(如前所述)。

答案 8 :(得分:1)

您无法使用自动属性。您必须使用支持字段以旧方式定义属性并手动调用该方法。

public class Person
{
    private string _FirstName;
    public string FirstName 
    { 
        get
        {
            return _FirstName;
        }
        set
        {
            SomeMethod();
            _FirstName = value;
        }
    }
    private void SomeMethod()
    {
        //do something
    }

}

答案 9 :(得分:0)

据我所知,你必须使用一个支持字段,然后将调用放入setter中的另一个方法:

public class Person {
    private string firstName;
    private string lastName;

    public string FirstName {
        set { 
            DoSomeStuff();
            firstName = value;
        }
        get { return firstName; }
    }

    public string LastName { 
        set {
            DoSomeStuff();
            lastName = value;
        }
        get { return lastName; }
    }
}

答案 10 :(得分:0)

是的,您可以使用装饰器设计模式。