微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 有没有办法在设置类的任何属性时调用方法?

所以我要做的是在设置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() {
    }

}

用法

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);

    }
}

原文地址:https://www.jb51.cc/csharp/92787.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐