Is there a way to intercept setters and getters in

2020-03-01 04:05发布

In both Ruby and PHP (and I guess other languages as well) there are some utility methods that are called whenever a property is set. ( *instance_variable_set* for Ruby, *__set* for PHP).

So, let's say I have a C# class like this:

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

Now, let's say that if any property setter from the Person class is called, I want to call another method first, and then continue with the default behaviour of the setter, and the same applies for the property setters.

Is this possible?


Edit: I want to do this without defining a backing field.

11条回答
We Are One
2楼-- · 2020-03-01 04:42

Not out of the box. You would need to insert code into each properties setter and getter, either manually or automatically using IL rewriting.

When you want to do it manually, you can't use automatic properties any more.
When you want to do it automatically, have a look at AOP.

查看更多
趁早两清
3楼-- · 2020-03-01 04:44

Not generally; a few options though;

  • inherit from ContextBoundObject - which does allow this, but at a performance cost
  • write an explicit property (i.e. with a backing field), and add a utility method call manually
  • look at compile-time weavers, such as PostSharp - generally by spotting an attribute or similar
  • look at runtime code generators, as offered by some DI/IoC tools (and some other "decorator" based tools) - which either decorate or subclass your object to add the extra code
查看更多
兄弟一词,经得起流年.
4楼-- · 2020-03-01 04:45

Are you in a position to rewrite your class to implement an interface? If so, Unity's interface interceptor might give you what you need. If an interface is not an option then that link also documents Unity's type and instance interceptors.

查看更多
混吃等死
5楼-- · 2020-03-01 04:45

As far as I know, you have to use a backing field and put the call to the other method inside the setter thusly:

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; }
    }
}
查看更多
看我几分像从前
6楼-- · 2020-03-01 04:47

It is possible to do directly in the property body itself, but then you need to use a proper backing field instead of auto-implemented properties.

private string firstName;

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

Even with auto-implemented properties you get a backing field - this is generated by the compiler and you don't have direct access to it.


Edit:

Seeing as you don't want a backing field, you have other options - using an AOP tool such as PostSharp could help with that.

查看更多
登录 后发表回答