问题
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.
回答1:
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
回答2:
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.
回答3:
You will have to write the properties in full to achieve this.
回答4:
I know this has been properly answered but I'll include an example to show you the syntax to achieve what you want:
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);
}
}
}
回答5:
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.
回答6:
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.
回答7:
Yes, of course...
In your example you are using automatic properties, without a backing field.... You just need to create a backing field for your property, and then you can do what you want in the setter and getter.
example:
private string firstName;
public string FirstName
{
get { return firstName; }
set { doMethod(); firstName = value;}
}
回答8:
Mocking frameworks can do this, as well as IoC libraries like Unity. The only other way to do such a thing would be to use IL-rewriting (as previously mentioned).
回答9:
You cant use automatic properties. You would have to dinfe the property out the old fashion way with a backing field and call the method manually.
public class Person
{
private string _FirstName;
public string FirstName
{
get
{
return _FirstName;
}
set
{
SomeMethod();
_FirstName = value;
}
}
private void SomeMethod()
{
//do something
}
}
回答10:
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; }
}
}
回答11:
Yes, you may use the Decorator Design Pattern.
来源:https://stackoverflow.com/questions/6030936/is-there-a-way-to-intercept-setters-and-getters-in-c