Как стать автором
Обновить

Комментарии 21

Если вы понимаете «разницу» между (1), (2), (3), то итоговая разница во времени случайна. (6) https://habrahabr.ru/post/281294/#comment_8847910
> Использование аоп тормознет приложение на прочь

Там проблема не в АОП. Это АОП курильщика.

Возьмите Fody/PropertyChanged, KindOfMagic.
Есть еще такой проект — AspectInjector разрабатыемый нами. В гитхабе как раз есть пример с INotifyPropertyChanged
речь идет о динамическом АОП, конкретная реализация АОП
KindOfMagic например, это статическое АОП
Некоторое время назад хотел добавить немного АОП в свой код, но не устраивала постобработка скомпиленного кода и совместимость с текущим пайплайном. В результате для этого делал свой велосипед.
Попробовал локально ваш тест прогнать, различия в районе 10% от 1-го решения. Мне кажется это более верная реализация АОП, если не хочется статического.
Если захочется проверить, то в вся документация в тестах. Но что бы не копаться можно использовать такую реализацию:
public class TestModel : NotificationObject, IData
{
  [NotifyProperty]
  public virtual int Value { get; set; }

  public TestModel()
  {
    Notificator.Create(this);
  }
}
Тяжело читать из-за колоссального количества орфографических и пунктуационных ошибок в тексте.
Что странно, я отписался в личку автору еще вчера утром, но до сих пор висят ошибки.
Только сейчас удалось выйти.
часть ошибок исправил, спасибо zodchiy
Ещё хотелось бы посмотреть код, с помощью которого получились данные результаты.
Выложу, чуть позже.
Обещанного три года ждут…
но мы ж не улитки

вот код программы

class Program
	{
		[STAThread]
		static void Main( string[] args )
		{
			IUnityContainer container = new UnityContainer();

			container.RegisterViewModel<DataAop>();
			var dataAop = container.Resolve<DataAop>();

			List<IData> listOfData = new List<IData>();
			listOfData.Add( dataAop );

			var asm = System.Reflection.Assembly.GetExecutingAssembly();

			var excludes = new HashSet<Type> { typeof( IData ), typeof( DataAop ), typeof( ProxyData ), typeof( DataObservableObject ) };

			listOfData.AddRange( asm.GetTypes()
				.Where( t => typeof( IData ).IsAssignableFrom( t ) && !excludes.Contains( t ) ).Select( t => Activator.CreateInstance( t ) as IData ) );

			foreach (var notify in listOfData.Cast<INotifyPropertyChanged>())
				notify.PropertyChanged += OnPropertyChanged;

			DataObservableObject observableData = new DataObservableObject();

			var propDesp = DependencyPropertyDescriptor.FromProperty( ObservableObject<int>.ValueProperty, typeof( ObservableObject<int> ) );
			propDesp.AddValueChanged( observableData.RealValue, OnPropertyChanged );

			listOfData.Add( observableData );

			Console.WriteLine( string.Format( "Start ---> {0}", DateTime.Now ) );

			Stopwatch sw = new Stopwatch();
			foreach (var data in listOfData)
			{
				sw.Restart();
				for (int i = 0; i < 10000000; i++)
					data.Value = i;
				sw.Stop();

                                Console.WriteLine();

				Console.WriteLine( string.Format( "Iteration date {0}, data name {1}, elapsed {2}",
					DateTime.Now, data.GetType().Name, sw.ElapsedMilliseconds ) );
			}

			Console.WriteLine( string.Format( "Stop ---> {0}", DateTime.Now ) );

			Console.ReadKey();
		}

		static void OnPropertyChanged( object sender, EventArgs e ) { }

		static void OnPropertyChanged( object sender, PropertyChangedEventArgs e ) { }
	}


интерфейс улиток (эх название у интерфейса подкачало)
public interface IData
    {
        int Value { get; set; }
    }


пример реализации
 class DataString : BindableBase, IData
    {
        int _value;

        public int Value
        {
            get
            {
                return _value;
            }

            set
            {
                if (_value != value)
                {
                    _value = value;
                    OnPropertyChanged("Value");
                }
            }
        }
    }


особо опасная реализация
 class DataObservableObject : IData
    {
        public DataObservableObject()
        {
            RealValue = new ObservableObject<int>();
        }
        public ObservableObject<int> RealValue { get; private set; }

        public int Value
        {
            get
            {
                return RealValue.Value;
            }

            set
            {
                RealValue.Value = value;
            }
        }
    }


запустил тест на другом компьютере, и вот результат
image
разница не велика
Что такое [CallerMemberName]? Как происходит определение имени текущего свойства?
Атрибут, появился в с#5 https://msdn.microsoft.com/ru-ru/library/system.runtime.compilerservices.callermembernameattribute(v=vs.110).aspx
имя подставляется во время выполнения
можно посмотреть https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices(v=vs.110).aspx
Во время выполнения, или таки во время компиляции? Судя по отсутствию разницы в производительности между методами 1, 2, и 3, я бы предположил, что подстановка происходит прямо в вызове метода во время компиляции.
Во время запуска при анализе байт кода, это делается только 1 раз
От куда вы все знаете?
Вот как вы пришли к этим знаниям?
И какие интерфейсы стоит изучать в первую очередь(.NET)?
Ну знаю я далеко не все
Стандартный путь дзена — быдлокодинг -> шаблоны -> solid -> быдлокодинг -> просветление
на самом деле очень важно работать в команде и обмениваться знаниями, а так же критика
И какие интерфейсы стоит изучать в первую очередь(.NET)?
что есть интерфейс?
Методы 1, 2 и 3 генерируют одинаковый IL код, разница лишь в предпочтении автора. 1-й может привести к ошибке, в случае переименования свойства,. 2-й метод в этом плане удобнее, т.к. инструмент вроде ReSharper автоматически переименует и свойство, и конструкцию nameof(Property). 5-й метод может быть удобен для реализации дополнительной логики: логирование, сравнение значений и генерация события лишь на действительном изменении значения, генерация события PropertyChanging а потом PropertyChanged. 4,6,7 не вижу смысла, да и вообще велосипеды облегчения реализации INotifyPropertyChanged не читаю, будто других проблем в WPF нет, как сэкономить 1 строку кода на 1-м свойстве. «Дабпиэф ничего не поделаешь» при отрисовке списка говорят, наверное, только джуны, никогда не читавшие исходников VirtualizingStackPanel и ItemsControl и не писавших свои панели, реализующие виртуализацию отображения, там в принципе нечему тормозить.
В целом поддерживаю, за исключением четвертой улитки, хорошая альтернатива nameof в условиях отсутствия c# 6 версии. Ну и про тормознутый список говорил не юниор, а разработчик которому было искрнни лень исправлять проблемный код
«Дабпиэф ничего не поделаешь» при отрисовке списка говорят, наверное, только джуны, никогда не читавшие исходников VirtualizingStackPanel

Это там, где по 20 реф-параметров передается? Ну действительно, тормозить совершенно нечему. Или по 3 цикла отрисовки на каждый элемент? Тоже норм.

Методы 1, 2 и 3 генерируют одинаковый IL код, разница лишь в предпочтении автора. 1-й может привести к ошибке, в случае переименования свойства,. 2-й метод в этом плане удобнее, т.к. инструмент вроде ReSharper автоматически переименует и свойство, и конструкцию nameof(Property).

Как раз-таки только решарпер переименует в первом случае и свойство, и имя, а вот студия внесет изменения только при явном использовании переменной в nameof.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории