簡體   English   中英

攔截調用C#中的屬性get方法

[英]Intercept call to property get method in C#

我們假設我們有這個類:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

現在,是否有可能在C#中攔截對屬性get方法的調用,運行其他一些方法並返回該方法的結果而不是屬性值? 我希望能夠在幕后做一些額外的邏輯。 缺點是這個類無法更改(在C#級別)。 也許有些IL?

看看PostSharp: http//www.sharpcrafters.com/

這實現了您正在尋找的東西,以及更多。

PostSharp實現面向方面的.NET編程。 它是一種商業產品。 很酷。

請注意,此問題的任何解決方案都將涉及一些運行時開銷(一些內存,一些額外的時間來進行函數調用。)沒有什么是完全免費的。

如果你的類無法更改 ,你可以使用像PostSharp這樣的工具 - 它允許你編織代碼來攔截或替換對方法和屬性的調用。

如果您可以更改代碼 ,那么只需避免使用自動屬性,並顯式實現get和set操作。 然后你可以做任何你需要的事情。 或者,您可以將屬性定義為虛擬,並派生另一個類來更改getter和/或setter的行為:

public class Person 
{ 
  public virtual int Id { get; set; } 
  public virtual string Name { get; set; } 
} 

public class PersonDerived : Person
{
  public override int Id { get { ... } set { ... } }
  public override string Name { get { ... } set { ... } }
}

如果您只需要進行單元測試 ,您可能需要查看MoqTypeMock模擬工具。

擴展課程並做

public class MyPerson : Person
{
    public new int Id 
    { 
        get
        {
            foo();
            return base.Id;
        }
}

.NET SDK已經滿足您的需求。 如果你小心的話,你可以通過反匯編/重組(ildasm.exe和ilasm.exe)往返CLR上的大多數東西。 確保啟動“Visual Studio命令提示符”,以便這些工具位於PATH中。

1)ildasm person.exe

2)文件 - >轉儲(person.il)

3)編輯和修改get_Name()方法:重要:在IL級別修改方法時,始終重新計算.maxstack ,因為Visual Studio .NET編譯器將為大多數方法准確設置它,如果添加任何代碼,則引發.maxstack用於處理該方法的運行時堆棧上的最大值數,如果不是,則會得到無效的程序。

  .method public hidebysig specialname instance string get_Name() cil managed
  {
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
    // Code size       11 (0xb)
    .maxstack  2
    .locals init (string V_0)
    IL_0000:  ldarg.0
    IL_0001:  ldfld      string Person::'<Name>k__BackingField'
    IL_0006:  stloc.0
    IL_0009:  ldloc.0
        IL_000a:  ldstr "IL code inserted here"
        call    void [mscorlib]System.Console::WriteLine(string)
    IL_001a:  ret
 } // end of method Person::get_Name

4)重新組裝:ilasm person.il

沒有自動屬性,沒有。

但你可以這樣做:

public class Person
{
    private int _id;

    public int Id
    {
        get
        {
            // Do some logic or call a method here
            return _id;
        }
        set
        {
            if(value <= 0)
                throw new CustomInvalidValueException();

            _id = value;
        }
    }
}
public Class Person
{
    private int _id;
    public int ID
    {
      get{ MyMethod(); return _id; }
      set{ _id = value; }
    }
   // etc. etc. .....

 }
private bool _pp;
public bool Propery
{
  get { // your code}
  set { _pp = value; }
}

我認為您正在尋找面向方面的框架

如果您無法更改類本身,則可以考慮使用擴展方法來獲取名稱。 這將改變您訪問數據的方式,因此它也可能不是一個選項。 如果您有興趣,這就是您的方法:

public static class PersonExtensions
{
    public static string GetName(this Person p)
    {
        foo();
        return p.Name;
    }
}

然后,您將以這種方式訪問​​該名稱:

Person myPerson = new Person();
string name = myPerson.GetName();  // Also calls foo() for you extra processing

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM