2011-05-17 76 views
30

在Ruby和PHP(我猜其他語言也是這樣)中,有一些實用程序方法在設置屬性時被調用。 (針對Ruby的* instance_variable_set *,針對PHP的* __ set *)。有沒有辦法攔截C#中的setter和getters?

所以,讓我們說我有一個C#類是這樣的:

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

現在,讓我們說,如果從Person類中的任何屬性setter被調用時,我想先調用另一個方法,然後繼續與設置者的默認行爲相同,同樣適用於屬性設置者。

這可能嗎?


編輯: 我想這樣做沒有定義支持字段。

+0

你現在展示的方法現在在MSIL中實現了一個後臺字段,所以你爲什麼不想要一個呢? – Mr47 2011-05-17 12:58:57

+0

@ Mr47 Sure,但我不想自己定義它。我想要一個自動的方式來做到這一點。 – 2011-05-17 13:00:16

+2

恐怕任何其他方式都比只有後臺場地更麻煩。 – Mr47 2011-05-17 13:01:58

回答

28

不一般;儘管如此,

  • 繼承ContextBoundObject - 這允許這樣做,但在性能成本
  • 寫一個明確的產權(即支持字段),並添加一個實用的方法調用手動
  • 看看編譯例如PostSharp - 通常通過發現屬性或類似
  • 查看運行時代碼生成器,如某些DI/IoC工具(以及其他一些「裝飾工具」工具)所提供的那樣 - 可以裝飾或子類化對象添加額外的代碼
+0

你能否提供一個鏈接,顯示如何通過'ContextBoundObject'完成這項工作?謝謝。 – 2011-05-17 12:54:03

+0

我覺得'DynamicObject'也可以用在這種情況下(重寫'TrySetMember')。但是如何能'ContextBoundObject'? – 2011-05-17 12:56:05

+0

@丹尼 - 最終,屬性是方法 - 所以這樣的事情應該工作:http://www.codeproject.com/KB/cs/aspectintercept.aspx – 2011-05-17 13:16:18

4

您將不得不完整寫入屬性才能實現此目的。

1

不開箱即用。您需要將代碼插入到每個屬性setter和getter中,手動或自動使用IL重寫。

如果您想手動執行此操作,則不能再使用自動屬性。
如果您想自動執行此操作,請查看AOP。

14

可以直接在屬性本身中完成,但是您需要使用適當的後臺字段而不是auto-implemented properties

private string firstName; 

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

即使是自動實現的屬性你會得到支持字段 - 這是由編譯器生成的,你不必直接訪問它。


編輯:

看到,因爲你不想支持字段,你還有其他的選擇 - 使用AOP工具,如PostSharp可以與幫助。

1

是的,當然...

在你的例子中,你正在使用自動屬性,沒有後臺字段....你只需要爲你的屬性創建一個後臺字段,然後你可以在setter和getter中做你想要的。

例如:

private string firstName; 

public string FirstName 
{ 
get { return firstName; } 

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

據我所知,你必須使用一個支持字段,並把調用其他方法的制定者正是如此裏面:

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

懲戒框架可以做這個以及IoC庫如Unity。做這樣的事情的唯一方法是使用IL重寫(如前所述)。

1

你不能使用自動屬性。你將不得不用老式的方式來抵擋財產,並且手動調用該方法。

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

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

你在一個位置,重寫你的類來實現一個界面?如果是這樣,Unity's interface interceptor可能會給你你所需要的。如果一個接口不是一個選項,那麼該鏈接還會記錄Unity的類型和實例攔截器。

0

是的,你可以使用裝飾設計模式。

相關問題