Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在设置类的任何属性时,是否有方法调用方法?_C#_Reflection_Properties_Delegates - Fatal编程技术网

C# 在设置类的任何属性时,是否有方法调用方法?

C# 在设置类的任何属性时,是否有方法调用方法?,c#,reflection,properties,delegates,C#,Reflection,Properties,Delegates,所以我要做的是,当C#类中的任何属性被设置时,调用一个单独的propertyWasSet()函数(反之,当它被设置为get时,调用propertyWasGot())。我还想知道调用了哪个属性的“get” 我想维护一个“set”属性的命令,如果“get”操作已经设置好,则检查它们(如果没有设置,则抛出一个错误) 我一直在查看msdn文档中的反射、委托等,但我不完全确定这是否可行 有办法做到这一点吗?或者在调用这些函数时触发一个事件,这些函数可以在基类或其他东西中被拦截?我认为您需要的与WPF de

所以我要做的是,当C#类中的任何属性被设置时,调用一个单独的propertyWasSet()函数(反之,当它被设置为get时,调用propertyWasGot())。我还想知道调用了哪个属性的“get”

我想维护一个“set”属性的命令,如果“get”操作已经设置好,则检查它们(如果没有设置,则抛出一个错误)

我一直在查看msdn文档中的反射、委托等,但我不完全确定这是否可行


有办法做到这一点吗?或者在调用这些函数时触发一个事件,这些函数可以在基类或其他东西中被拦截?

我认为您需要的与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()操作,这样就不必显式地更改所有对象的实例化。我要玩这个。非常感谢!我认为您真的需要为您的对象创建一个工厂,这可能是一个更好的实践(因为它允许您在以后交换对象实现并缓存对象实例)