如何实现类属性修改来源检测,外部修改时自定义抛出异常
解决方案
修改后的代码
using System.Diagnostics; public class MyClass { private int position; public int Position { get => position; set { // 获取调用栈的上一帧(跳过当前set访问器的帧) var callerFrame = new StackTrace().GetFrame(1); var callerMethod = callerFrame.GetMethod(); // 判断调用方是否属于当前类或其子类 if (callerMethod.DeclaringType != GetType() && !callerMethod.DeclaringType.IsSubclassOf(GetType())) { throw new InvalidOperationException("无法从外部修改Position属性"); } position = value; } } // 内部示例方法:可以正常修改Position public void UpdatePositionInternally(int newPosition) { Position = newPosition; // 不会抛出异常 } }
实现逻辑
- 放开访问限制:把原本的
private set改为public set,消除编译阶段的访问拦截,允许外部代码发起赋值操作。 - 识别调用来源:通过
StackTrace获取调用栈信息,定位发起赋值的方法所属类型:- 若调用方是当前类或其子类的成员,判定为内部修改,正常执行赋值;
- 若调用方是外部类型,直接抛出
InvalidOperationException异常。
注意事项
- 性能开销:
StackTrace会遍历调用栈,存在一定性能损耗,若该属性属于高频调用场景,需权衡使用; - 子类兼容:代码已包含子类调用的判断逻辑,若无需支持子类修改,可简化条件为
callerMethod.DeclaringType != GetType(); - 内部调用规范:类内部修改属性时,直接使用
Position = 值即可,代码会自动识别为合法内部操作。
内容的提问来源于stack exchange,提问作者ThePenguin
相关产品推荐
相关产品推荐

