通过 Castle 的 DynamicProxy 处理 PropertyChanging/PropertyChanged

发布于 2024-12-22 01:24:36 字数 772 浏览 1 评论 0原文

我目前有一个如下所示的 setter 方法:

 private string _a;
    public virtual string A
    {
        get { return _a; }
        set
        {
            if (_a!= value)
            {
                if (this.OnPropertyChanging("A", _a, value))
                {
                    var previousValue = _a;
                    _a = value;
                    this.OnPropertyChanged("A", previousValue, value);
                }
            }

        }
    }

我在 Wily 博士的学徒 (http://stackoverflow.com/a/8578507/981225) 的帮助下实现了此方法,并使用自定义的更改处理程序来跟踪旧的和当前的值,以及将更改事件设置为“已取消”的能力,以便不会发生 PropertyChange。

这非常有效。然而,我们有数百个属性,并且有很多重复的代码。

我过去使用过 Castle 的 DynamicProxy,以避免编写“OnPropertyChanged("A")”。

作为代理拦截方法的一部分,如何实现此 setter 中的逻辑?是否可以?谢谢。

I currently have a setter method which looks like this:

 private string _a;
    public virtual string A
    {
        get { return _a; }
        set
        {
            if (_a!= value)
            {
                if (this.OnPropertyChanging("A", _a, value))
                {
                    var previousValue = _a;
                    _a = value;
                    this.OnPropertyChanged("A", previousValue, value);
                }
            }

        }
    }

I have implemented this with help from Dr Wily's Apprentice (http://stackoverflow.com/a/8578507/981225), with a custom Changing handler that keeps track of the old and current value, as well as the ability to set the Changing event as 'Cancelled', such that the PropertyChange will not occur.

This works perfectly. However, we have hundreds of properties and this is a lot of code the duplicate.

I have used Castle's DynamicProxy in the past, to avoid having to write 'OnPropertyChanged("A")'.

How can I implement the logic within this setter, as part of the Proxy's Intercept method? Is it possible? Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

过气美图社 2024-12-29 01:24:36

也许我有点晚了,但我在 Linq-To-SharePoint 模型中遇到了类似的任务。如果有人仍然想知道的话,我画了一些代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.DynamicProxy;
using System.Reflection;
using System.ComponentModel;


namespace DemoSpace
{
    public abstract class EntityBase : INotifyPropertyChanged, INotifyPropertyChanging
    {
        public virtual void OnPropertyChanging(string propertyName, object value)
        {
            if ((null != PropertyChanging))
            {
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }

        public virtual void OnPropertyChanged(string propertyName)
        {
            if ((null != PropertyChanged))
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler  PropertyChanged;

        public event PropertyChangingEventHandler  PropertyChanging;
    }

    public class DemoInterceptor<T> : IInterceptor where T : EntityBase
    {
        private T _target;

        public DemoInterceptor(T target)
        {
            _target = target;
        }

        public void Intercept(IInvocation invocation)
        {
            if (invocation.Method.IsPublic && invocation.Method.Name.StartsWith("set_"))
            {
                string propertyName = invocation.Method.Name.Substring(4);
                string privateFieldName = ResolvePropName(propertyName); 


                object original_value = 
                    typeof(T).GetField(privateFieldName, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(_target);

                _target.OnPropertyChanging(propertyName, original_value);
                invocation.Method.Invoke(_target, invocation.Arguments);
                _target.OnPropertyChanged(propertyName);

            }
            else
            {
                invocation.ReturnValue = invocation.Method.Invoke(_target, invocation.Arguments);
            }

        }

        public virtual string ResolvePropName(string propertyName)
        {
            return "_" + propertyName.Substring(0, 1).ToLower() + propertyName.Substring(1);
        }

    }
}

Maybe I'm a bit late, but I came across a similar task in the Linq-To-SharePoint model. I sketched some code if some one's still wondering.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.DynamicProxy;
using System.Reflection;
using System.ComponentModel;


namespace DemoSpace
{
    public abstract class EntityBase : INotifyPropertyChanged, INotifyPropertyChanging
    {
        public virtual void OnPropertyChanging(string propertyName, object value)
        {
            if ((null != PropertyChanging))
            {
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }

        public virtual void OnPropertyChanged(string propertyName)
        {
            if ((null != PropertyChanged))
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler  PropertyChanged;

        public event PropertyChangingEventHandler  PropertyChanging;
    }

    public class DemoInterceptor<T> : IInterceptor where T : EntityBase
    {
        private T _target;

        public DemoInterceptor(T target)
        {
            _target = target;
        }

        public void Intercept(IInvocation invocation)
        {
            if (invocation.Method.IsPublic && invocation.Method.Name.StartsWith("set_"))
            {
                string propertyName = invocation.Method.Name.Substring(4);
                string privateFieldName = ResolvePropName(propertyName); 


                object original_value = 
                    typeof(T).GetField(privateFieldName, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(_target);

                _target.OnPropertyChanging(propertyName, original_value);
                invocation.Method.Invoke(_target, invocation.Arguments);
                _target.OnPropertyChanged(propertyName);

            }
            else
            {
                invocation.ReturnValue = invocation.Method.Invoke(_target, invocation.Arguments);
            }

        }

        public virtual string ResolvePropName(string propertyName)
        {
            return "_" + propertyName.Substring(0, 1).ToLower() + propertyName.Substring(1);
        }

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文