C# 中拦截对属性 get 方法的调用
假设我们有这个类:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
现在,在 C# 中是否可以拦截对属性 get 方法的调用,运行其他方法并返回该方法的结果而不是属性值?我希望能够在幕后做一些额外的逻辑。 缺点是此类无法更改(在 C# 级别)。也许一些IL?
Let's assume that we have this class:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
Now, is it possible in C# to intercept call to property get method, run some other method and return result of that method instead of property value? I'd like to be able to do some additional logic behind the scene.
The downside is that this class can't be changed (on C# level). Maybe some IL ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
查看 PostSharp: http://www.sharpcrafters.com/
这正是您正在寻找的东西,还有更多。
PostSharp 实现了 .NET 的面向方面编程。它是一种商业产品。非常酷。
请注意,此问题的任何解决方案都会涉及一些运行时开销(一些内存、一些额外的函数调用时间。)没有什么是绝对免费的。
Look into PostSharp: http://www.sharpcrafters.com/
This implements exactly what you're looking for, and a whole lot more.
PostSharp implements Aspect Oriented Programming for .NET. Its a commercial product. Very cool.
Just be aware that any solution to this problem will involve some runtime overhead (some memory, some extra time to make function calls.) Nothing is absolutely free.
如果您的课程无法更改,您可以考虑使用 PostSharp - 它允许您编写拦截或替换对方法和属性的调用的代码。
如果您可以更改代码,那么只需避免使用自动属性,并显式实现 get 和 set 操作即可。然后你就可以做任何你需要做的事情了。或者,您可以将属性定义为 virtual 并派生另一个类来更改 getter 和/或 setter 的行为:
如果您仅需要它进行单元测试,您可能需要研究模拟工具,例如Moq 或 TypeMock。
If your class can't be changed, you can look into using tools like PostSharp - it allows you to weave in code that intercepts or replaces calls to methods and properties.
If you can change the code, then just avoid using an automatic property, and implement the get and set operations explicitly. Then you can do whatever you need. Alternatively, you can define the property as virtual and derive another class to change th behavior of the getter and/or setter:
If you need this just for unit testing, you may want to look into mocking tools like Moq or TypeMock.
.NET SDK 已经具备您所需要的功能。如果您小心的话,您可以通过反汇编/重组(ildasm.exe 和 ilasm.exe)来往返 CLR 上的大多数内容。确保启动“Visual Studio 命令提示符”,以便这些工具位于您的路径中。
1) ildasm person.exe
2) 文件->转储(person.il)
3) 编辑修改get_Name()方法:
重要提示:在 IL 级别修改方法时,请始终重新计算 .maxstack,因为 Visual Studio .NET 编译器将为大多数方法准确设置它,如果添加任何代码,请提高 .maxstack 来处理该方法的运行时堆栈上的最大值数,如果不是,您将得到一个无效的程序。
4)重新组装:ilasm person.il
The .NET SDK has what you need already. You can round-trip most anything on the CLR by disassembly/reassembly (ildasm.exe and ilasm.exe) if you are careful. Make sure to start a "Visual Studio Command Prompt" so these tools are in your PATH.
1) ildasm person.exe
2) File -> Dump (person.il)
3) Edit and modify the get_Name() method:
IMPORTANT: When modifying a method at the IL level, always recalculate .maxstack, since the Visual Studio .NET compilers will have set it exactly for most methods, if you add any code, raise .maxstack to handle the maximum # of values on the runtime stack for that method, if not you'll get an invalid program.
4) Re-assemble : ilasm person.il
扩展课程并做
Extend the class and do
不具有自动属性,不。
但你可以这样做:
Not with auto-properties, no.
But you could do:
我认为您正在寻找面向方面的框架。
I think you're looking for an Aspect Oriented Framework.
如果您无法更改类本身,您可以考虑使用扩展方法来获取名称。这将改变您访问数据的方式,因此它可能也不是一个选择。如果您有兴趣,这就是您的做法:
然后您可以通过以下方式访问该名称:
希望这会有所帮助。
If you can't change the class itself, you might consider using an extension method to get the name. This will change the way you access the data, so it might not be an option either. This is how you'd do it, if you're interested:
You would then access the name this way:
Hope this helps.