Осуществление корректной реализации INotifyPropertyChanged с CodeContracts - “требует бездоказательный”

Измените URL следующим образом:

import requests
from bs4 import BeautifulSoup as bs

r = requests.get('http://www.mae.com.ar/mercados/Forex/Default.aspx')
soup = bs(r.content, 'lxml')
quote = soup.select_one('#ctl00_ContentPlaceHolder1_GVPREREFBCRA_ctl02_Label20').text
5
задан hwiechers 25 October 2009 в 20:10
поделиться

3 ответа

I assume you mean with the static analysis tools? (I would expect the runtime check to work, at least - and you could presumably leave it in debug builds). I doubt that this is something that static analysis is going to be able to see through - GetType().GetProperties() is simply too complex, etc.

In short; I doubt it... lambdas (Expression) are an option, but they are much slower than passing just a string.

1
ответ дан 14 December 2019 в 19:17
поделиться

Хорошо, во-первых, для этого я лично использую реализацию ObservableObject из MVVM foundation . Это проверка времени выполнения только для сборки DEBUG, почти идентичная вашей.

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
    this.VerifyPropertyName(propertyName);

    PropertyChangedEventHandler handler = this.PropertyChanged;
    if (handler != null)
    {
        var e = new PropertyChangedEventArgs(propertyName);
        handler(this, e);
    }
}

[Conditional("DEBUG")]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
    // Verify that the property name matches a real,  
    // public, instance property on this object.
    if (TypeDescriptor.GetProperties(this)[propertyName] == null)
    {
        string msg = "Invalid property name: " + propertyName;

        if (this.ThrowOnInvalidPropertyName)
            throw new Exception(msg);
        else
            Debug.Fail(msg);
    }
}

Это, вероятно, самый простой способ, но у него есть определенные недостатки: вам нужно иметь возможность наследовать от некоторого базового класса, он работает только во время выполнения (хотя это было всегда достаточно в моем wpf-опыте), это наверняка выглядит как «патч» для отсутствующей статической проверки.

У вас есть несколько способов включить статический анализ / статические инструменты для этого случая:

  1. Как говорит Марк, использовать лямбда-нотацию и извлекать строку во время выполнения .
  2. Написать собственное правило FxCop .
  3. Используйте инструмент AOP для постобработки кода с некоторой мета-разметкой.

Что касается CodeContracts, Я считаю, что он еще недостаточно зрел, чтобы обрабатывать такого рода проверки в статическом анализе. Представьте, он должен проанализировать вашу лямбду, понять, как это может быть неудачно из-за неправильного propertyName , найти все вызовы этого метода, выяснить все возможные входные данные и т. Д. Это просто неподходящий инструмент для такого рода чека.

3
ответ дан 14 December 2019 в 19:17
поделиться

The way I have done this in the past is to use our good friend Lambda. By using Expressions we can pass in the properties themselves to your implementation of OnPropertyChanges, and use the Expression tree to extract the property. This gives you compile time checking of the members you are raising the PropertyChanged event for.

Of course use of Expression will depend entirely on what type of performance you need.

See code snippet below:

using System;
using System.Linq;
using System.ComponentModel;
using System.Linq.Expressions;

namespace OnNotifyUsingLambda
{
    public class MainClass : INotifyPropertyChanged
    {
         public static void Main (string[] args) { new MainClass().Run();}
         public void Run()
         {
              this.PropertyChanged += (sender, e) => Console.WriteLine(e.PropertyName);
              MyProperty = "Hello";
         }

         private string myProperty;
         public string MyProperty  
         {
             get
             {
                 return myProperty;
             }
             set
             {
                 myProperty = value;
                 // call our OnPropertyChanged with our lamba expression, passing ourselves.
                 // voila compile time checking that we haven't messed up!
                 OnPropertyChanged(x => x.MyProperty); 
              }
         }  

         /// <summary>
         /// Fires the PropertyChanged for a property on our class.
         /// </summary>
         /// <param name="property">
         /// A <see cref="Expression<Func<MainClass, System.Object>>"/> that contains the 
         /// property we want to raise the event for.
         /// </param>
         private void OnPropertyChanged (Expression<Func<MainClass, object>> property)
         {
             // pull out the member expression (ie mainClass.MyProperty)
             var expr = (MemberExpression)property.Body; 

             if (PropertyChanged != null)
             {
                 // Extract everything after the period, which is our property name.
                 var propName = expr.ToString ().Split (new[] { '.' })[1];
                 PropertyChanged (this, new PropertyChangedEventArgs(propName));
             }
          }

          public event PropertyChangedEventHandler PropertyChanged;
     }
}
1
ответ дан 14 December 2019 в 19:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: