我们假设我们有这个类:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
现在,是否可以在C#中拦截对属性get方法的调用,运行其他一些方法并返回该方法的结果而不是属性值?我希望能够在幕后做一些额外的逻辑。 缺点是这个类无法更改(在C#级别)。也许有些IL?
答案 0 :(得分:7)
查看PostSharp:http://www.sharpcrafters.com/
这实现了你正在寻找的东西,以及更多。
PostSharp为.NET实现面向方面编程。它是一种商业产品。很酷。
请注意,此问题的任何解决方案都会涉及一些运行时开销(一些内存,一些额外的时间来进行函数调用。)没有什么是完全免费的。
答案 1 :(得分:6)
如果您的课程无法更改,您可以查看使用PostSharp等工具 - 它允许您编写代码来拦截或替换对方法和属性的调用。< / p>
如果您可以更改代码,则只需避免使用自动属性,并明确实施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 { ... } }
}
答案 2 :(得分:1)
扩展课程并执行
public class MyPerson : Person
{
public new int Id
{
get
{
foo();
return base.Id;
}
}
答案 3 :(得分:1)
.NET SDK已经满足您的需求。如果你小心的话,你可以通过反汇编/重组(ildasm.exe和ilasm.exe)往返CLR上的大多数东西。确保启动“Visual Studio命令提示符”,以便这些工具位于PATH中。
1)ildasm person.exe
2)文件 - &gt;转储(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
答案 4 :(得分:0)
没有自动属性,没有。
但你可以这样做:
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;
}
}
}
答案 5 :(得分:0)
public Class Person
{
private int _id;
public int ID
{
get{ MyMethod(); return _id; }
set{ _id = value; }
}
// etc. etc. .....
}
答案 6 :(得分:0)
private bool _pp; public bool Propery { get { // your code} set { _pp = value; } }
答案 7 :(得分:0)
我认为你正在寻找Aspect Oriented Framework。
答案 8 :(得分:0)
如果您无法更改类本身,可以考虑使用扩展方法来获取名称。这将改变您访问数据的方式,因此它也可能不是一个选项。如果您有兴趣,这就是您的工作方式:
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
希望这有帮助。