[英]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 { ... } }
}
擴展課程並做
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.