Обработка PropertyChanging / PropertyChanged через Castle's DynamicProxy - PullRequest
1 голос
/ 20 декабря 2011

В настоящее время у меня есть метод установки, который выглядит следующим образом:

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

        }
    }

Я реализовал это с помощью ученика доктора Уили (http://stackoverflow.com/a/8578507/981225),) с помощью пользовательского обработчика Changing, который отслеживает старое и текущее значение, а также возможностью установить событие Changing как «Отменено», так что Изменение свойства не произойдет.

Это отлично работает. Тем не менее, у нас есть сотни свойств, и это много кода-дубликата.

Я использовал DynamicProxy Касла в прошлом, чтобы избежать необходимости писать 'OnPropertyChanged ("A") ".

Как я могу реализовать логику в этом установщике, как часть метода Перехват Прокси? Является ли это возможным? Спасибо.

1 Ответ

1 голос
/ 23 августа 2012

Возможно, я немного опоздал, но я столкнулся с аналогичной задачей в модели 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);
        }

    }
}
...