Есть ли способ перехватывать сеттеров и геттеров в C#?

в Ruby и PHP (и, я думаю, других языках) есть некоторые методы утилиты, которые вызываются всякий раз, когда установлено свойство. ( * instance_variable_set* Рубина, * _ _ set* для PHP).

Итак, предположим, у меня есть класс C#, как это:

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

теперь предположим, что если какой-либо задатчик свойств из Person вызывается класс, сначала я хочу вызвать другой метод, а затем продолжить поведение сеттера по умолчанию и то же самое относится и к установщикам свойств.

это возможно?


Edit: Я хочу сделать это без определения резервного поля.

11 ответов


Не вообще; несколько вариантов, хотя;

  • наследовать от объекта contextboundobject, которые тут разрешить это, но ценой производительности
  • напишите явное свойство (т. е. С полем поддержки) и добавьте вызов метода утилиты вручную
  • посмотрите на ткачей времени компиляции, таких как PostSharp - обычно путем выделения атрибута или аналогичного
  • посмотрите на генераторы кода времени выполнения, как предлагают некоторые DI / IOC tools (и некоторые другие инструменты на основе "декоратора") - которые либо украшают, либо подкласс вашего объекта, чтобы добавить дополнительный код

Это можно сделать непосредственно в самом теле свойства, но тогда вам нужно использовать правильное поле поддержки вместо автоматически реализуемые свойства.

private string firstName;

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

даже с автоматически реализованными свойствами вы получаете резервное поле-это генерируется компилятором, и у вас нет прямого доступа к нему.


изменить:

видя, что вам не нужно резервное поле, у вас есть другие варианты-использование инструмента AOP, такого как PostSharp может помочь с этим.


вам придется написать свойства в полном объеме, чтобы достичь этого.


Я знаю, что на это был правильный ответ, но я включу пример, чтобы показать вам синтаксис для достижения того, что вы хотите:

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);
        }
    }
}

вы в состоянии переписать свой класс для реализации интерфейса? Если так, то перехватчик интерфейса Unity может дать вам то, что вам нужно. Если интерфейс не является опцией, то эта ссылка также документирует перехватчики типа и экземпляра Unity.


не из коробки. Вам нужно будет вставить код в каждый сеттер и геттер свойств вручную или автоматически с помощью перезаписи IL.

Если вы хотите сделать это вручную, вы больше не можете использовать автоматические свойства.
Если вы хотите сделать это автоматически, посмотрите на AOP.


Да, конечно...

в вашем примере вы используете автоматические свойства без резервного поля.... Вам просто нужно создать резервное поле для вашей недвижимости, а затем вы можете делать то, что вы хотите в сеттер и геттер.

пример:

private string firstName;

public string FirstName
{
 get { return firstName; }

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

насмешливые фреймворки могут это сделать, а также библиотеки МОК, такие как единство. Единственный способ сделать это - использовать IL-rewriting (как упоминалось ранее).


вы не можете использовать автоматические свойства. Вы должны были бы dinfe свойство из старого способа моды с полем поддержки и вызвать метод вручную.

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

}

насколько я знаю, вы должны использовать резервное поле и поместить вызов другого метода внутри сеттера таким образом:

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; }
    }
}

Да, вы можете использовать шаблон проектирования декоратор.