C# 在设置类的任何属性时,是否有方法调用方法?
所以我要做的是,当C#类中的任何属性被设置时,调用一个单独的propertyWasSet()函数(反之,当它被设置为get时,调用propertyWasGot())。我还想知道调用了哪个属性的“get” 我想维护一个“set”属性的命令,如果“get”操作已经设置好,则检查它们(如果没有设置,则抛出一个错误) 我一直在查看msdn文档中的反射、委托等,但我不完全确定这是否可行C# 在设置类的任何属性时,是否有方法调用方法?,c#,reflection,properties,delegates,C#,Reflection,Properties,Delegates,所以我要做的是,当C#类中的任何属性被设置时,调用一个单独的propertyWasSet()函数(反之,当它被设置为get时,调用propertyWasGot())。我还想知道调用了哪个属性的“get” 我想维护一个“set”属性的命令,如果“get”操作已经设置好,则检查它们(如果没有设置,则抛出一个错误) 我一直在查看msdn文档中的反射、委托等,但我不完全确定这是否可行 有办法做到这一点吗?或者在调用这些函数时触发一个事件,这些函数可以在基类或其他东西中被拦截?我认为您需要的与WPF de
有办法做到这一点吗?或者在调用这些函数时触发一个事件,这些函数可以在基类或其他东西中被拦截?我认为您需要的与WPF dependency property system非常相似。您可能想看看它的实现。无论如何,您也可以将拦截代码添加到每个属性的getter和setter中。您可能需要研究这类任务。它被设计为在C#(或任何.NET语言)之上运行,并且有一个好处,即不会因为反射而使代码混乱。事实上,我不相信你能找到一个完全使用C#/Reflection的解决方案,而不向你的每个属性手动添加代码,因此,我肯定会推荐PostSharp作为一种方式。如果你不自己创建它,就不会有这样的事情。前几周我为Set编写了一个拦截器,它可以很容易地为Get扩展,它使用RealProxy,这意味着你的基类需要派生出MarshalByRefObject 另一个奇特的选择是将类抽象,并使用反射发射构造一个封装所有属性的具体类 你也可以看看代码生成器来解决这个问题,或者 这个解决方案的性能不是很好,但是对于大多数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() {
}
}
公共接口iInterceptorNotified{
void OnPropertyChanged(字符串propertyName);
}
///
///一个简单的基于RealProxy的属性拦截器
///无论何时更改子对象的属性,都将调用OnPropertyChanged
///
公共类拦截器,其中T:MarshallByRefObject,IInterceptorNotifiable,new(){
类InterceptorProxy:RealProxy{
T代理;
T靶;
EventHandler OnPropertyChanged;
公共拦截器Proxy(T目标)
:基础(类型(T)){
this.target=目标;
}
公共重写对象GetTransparentProxy(){
proxy=(T)base.GetTransparentProxy();
返回代理;
}
公共覆盖IMessage调用(IMessage msg){
IMethodCallMessage调用=消息作为IMethodCallMessage;
如果(调用!=null){
var result=InvokeMethod(调用);
if(call.MethodName.StartsWith(“set_”)){
string propName=call.MethodName.Substring(4);
target.OnPropertyChanged(propName);
}
返回结果;
}否则{
抛出新的NotSupportedException();
}
}
IMethodReturnMessage调用方法(IMethodCallMessage callMsg){
返回RemotingServices.ExecuteMessage(target,callMsg);
}
}
publicstatict-Create(){
var interceptor=newinterceptorproxy(newt());
return(T)interceptor.GetTransparentProxy();
}
专用拦截器(){
}
}
用法:
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);
}
}
类Foo:MarshallByRefObject,IInterceptorNotifiable{
public int PublicProp{get;set;}
公共字符串lastPropertyChanged;
公共void OnPropertyChanged(字符串propertyName){
lastPropertyChanged=propertyName;
}
}
[测试]
public void TestPropertyInterception(){
var foo=Interceptor.Create();
foo.PublicProp=100;
Assert.AreEqual(“PublicProp”,foo.lastPropertyChanged);
}
}
请求的设置部分与WPF依赖属性系统非常相似。
但是GET部分非常不寻常,甚至在WPF依赖属性系统中也没有 是的,我试图避免在每个属性中添加检查,因为有几个属性,每个属性的代码几乎相同。我考虑过在运行时创建一个新类,并将所有类属性包装到一个方法中,然后继续它的正常业务,但我不确定这是否可行,很快就变得复杂了,这真的很有趣。我假设我可以在对象的构造函数中执行Create()操作,这样就不必显式地更改所有对象的实例化。我要玩这个。非常感谢!我认为您真的需要为您的对象创建一个工厂,这可能是一个更好的实践(因为它允许您在以后交换对象实现并缓存对象实例)