6 c# reflection delegates properties
所以我要做的是在设置C#类中的任何属性时调用单个propertyWasSet()函数(相反,当获取时为propertyWasGot()).我还想知道调用哪个属性'get'.
我想保持一个'设置'属性的dictonary,并检查'get'动作是否已经设置(并且如果没有则抛出错误).
我正在通过msdn文档查看反思,代表等...,但我不完全确定这是可能的.
有没有办法做到这一点?或者在调用其中一个可以在基类中拦截的函数时触发事件?
我为Set编写了一个拦截器,它可以很容易地为Get扩展,它使用RealProxy,这意味着你的基类需要派生出MarshalByRefObject.
另一个奇特的选择是让你的类抽象,并使用Reflection Emit构造一个包装所有属性的具体类.
你也可以看看代码生成器来解决这个问题或PostSharp ...
这个解决方案的性能并不是很好,但对于大多数UI绑定来说它应该足够快.可以通过生成用于代理调用的LCG方法来改进它.
public interface IInterceptorNotifiable {
void OnPropertyChanged(string propertyName);
}
/// <summary>
/// A simple RealProxy based property interceptor
/// Will call OnPropertyChanged whenever and property on the child object is changed
/// </summary>
public class Interceptor<T> where T : MarshalByRefObject, IInterceptorNotifiable, new() {
class InterceptorProxy : RealProxy {
T proxy;
T target;
EventHandler<PropertyChangedEventArgs> OnPropertyChanged;
public InterceptorProxy(T target)
: base(typeof(T)) {
this.target = target;
}
public override object GetTransparentProxy() {
proxy = (T)base.GetTransparentProxy();
return proxy;
}
public override IMessage Invoke(IMessage msg) {
IMethodCallMessage call = msg as IMethodCallMessage;
if (call != null) {
var result = InvokeMethod(call);
if (call.MethodName.StartsWith("set_")) {
string propName = call.MethodName.Substring(4);
target.OnPropertyChanged(propName);
}
return result;
} else {
throw new NotSupportedException();
}
}
IMethodReturnMessage InvokeMethod(IMethodCallMessage callMsg) {
return RemotingServices.ExecuteMessage(target, callMsg);
}
}
public static T Create() {
var interceptor = new InterceptorProxy(new T());
return (T)interceptor.GetTransparentProxy();
}
private Interceptor() {
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
class Foo : MarshalByRefObject, IInterceptorNotifiable {
public int PublicProp { get; set; }
public string lastPropertyChanged;
public void OnPropertyChanged(string propertyName) {
lastPropertyChanged = propertyName;
}
}
[Test]
public void TestPropertyInterception() {
var foo = Interceptor<Foo>.Create();
foo.PublicProp = 100;
Assert.AreEqual("PublicProp", foo.lastPropertyChanged);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3177 次 |
| 最近记录: |