Подтвердить что ты не робот

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

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

Итак, скажем, у меня есть класс С# следующим образом:

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

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

Возможно ли это?


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

4b9b3361

Ответ 1

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

  • наследовать от ContextBoundObject - что позволяет это, но при производительности
  • записать явное свойство (т.е. с помощью поля поддержки) и добавить вызов метода утилиты вручную
  • Посмотрите на ткачишек времени компиляции, таких как PostSharp - обычно путем определения атрибута или подобного
  • посмотрите на генераторы кода времени выполнения, предлагаемые некоторыми инструментами DI/IoC (и некоторыми другими инструментами, основанными на декораторе) - которые либо украшают, либо подклассифицируют ваш объект, чтобы добавить дополнительный код

Ответ 2

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

private string firstName;

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

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


Edit:

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

Ответ 3

Вам нужно будет написать свойства полностью, чтобы достичь этого.

Ответ 4

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

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

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

Ответ 6

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

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

Ответ 7

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

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

Пример:

private string firstName;

public string FirstName
{
 get { return firstName; }

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

Ответ 8

Mocking frameworks могут это сделать, а также библиотеки IoC, такие как Unity. Единственный способ сделать это - использовать IL-переписывание (как упоминалось ранее).

Ответ 9

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

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

}

Ответ 10

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

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

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