Надеемся, что это поможет:
public static int countOfStringInAText(String stringToBeSearched, String masterString){
int count = 0;
while (masterString.indexOf(stringToBeSearched)>=0){
count = count + 1;
masterString = masterString.substring(masterString.indexOf(stringToBeSearched)+1);
}
return count;
}
Без использования чего-то вроде postharp в минимальной версии, которую я использую, используется что-то вроде:
public class Data : INotifyPropertyChanged
{
// boiler-plate
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, string propertyName)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
// props
private string name;
public string Name
{
get { return name; }
set { SetField(ref name, value, "Name"); }
}
}
Каждое свойство в таком случае выглядит примерно так:
private string name;
public string Name
{
get { return name; }
set { SetField(ref name, value, "Name"); }
}
что не очень много; при желании его также можно использовать в качестве базового класса. bool
, возвращаемый из SetField
, сообщает вам, было ли это отключением, если вы хотите применить другую логику.
или даже проще с C # 5:
protected bool SetField<T>(ref T field, T value,
[CallerMemberName] string propertyName = null)
{...}
, который можно вызвать так:
set { SetField(ref name, value); }
, с которым компилятор автоматически добавит «Имя»
.
C # 6.0 упрощает реализацию:
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
... а теперь с C # 7:
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private string name;
public string Name
{
get => name;
set => SetField(ref name, value);
}
Мне очень нравится решение Марка, но я думаю, что его можно немного улучшить, чтобы избежать использования «волшебной строки» (которая не поддерживает рефакторинг). Вместо использования имени свойства в виде строки его легко сделать лямбда-выражением:
private string name;
public string Name
{
get { return name; }
set { SetField(ref name, value, () => Name); }
}
Просто добавьте следующие методы в код Марка, и это поможет:
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
if (selectorExpression == null)
throw new ArgumentNullException("selectorExpression");
MemberExpression body = selectorExpression.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The body must be a member expression");
OnPropertyChanged(body.Member.Name);
}
protected bool SetField<T>(ref T field, T value, Expression<Func<T>> selectorExpression)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(selectorExpression);
return true;
}
Кстати, это было вдохновлено this сообщение в блоге обновленный URL-адрес
На самом деле у меня еще не было возможности попробовать это сам, но в следующий раз, когда я создаю проект с большими требованиями для INotifyPropertyChanged, я собираюсь написать Атрибут Postsharp , который будет внедрять код во время компиляции. Что-то вроде:
[NotifiesChange]
public string FirstName { get; set; }
Превратится в:
private string _firstName;
public string FirstName
{
get { return _firstname; }
set
{
if (_firstname != value)
{
_firstname = value;
OnPropertyChanged("FirstName")
}
}
}
Я не уверен, сработает ли это на практике, и мне нужно сесть и попробовать, но я не понимаю, почему бы и нет. Мне может потребоваться заставить его принимать некоторые параметры в ситуациях, когда необходимо активировать более одного OnPropertyChanged (если, например, у меня было свойство FullName в указанном выше классе)
В настоящее время я использую настраиваемый шаблон в Resharper, но даже с этим я устаю от того, что все мои владения такие длинные.
Ах, быстрый поиск в Google (который я должен был сделать до того, как написал это) показывает, что по крайней мере один человек делал что-то подобное до здесь . Не совсем то, что я имел в виду, но достаточно близко, чтобы показать, что теория верна.
Подход, очень похожий на АОП, заключается во внедрении материала INotifyPropertyChanged в уже созданный объект на лету. Вы можете сделать это с помощью чего-то вроде Castle DynamicProxy. Вот статья, объясняющая этот метод:
Другие вещи, которые вы можете принять во внимание при реализации такого рода свойств, - это тот факт, что оба INotifyPropertyChang * ed *ing используют классы аргументов событий.
Если у вас есть большое количество настраиваемых свойств, тогда количество экземпляров класса аргументов события может быть огромным, вам следует рассмотреть возможность их кеширования, поскольку они являются одной из областей, в которых может произойти взрыв строки.
Взгляните на это реализация и объяснение, почему это было задумано.
Поговорим о чрезмерной инженерии. Это значительно сложнее, чем , просто делать это правильно и дает мало пользы или вообще не дает. Если ваша IDE поддерживает фрагменты кода (Visual Studio / MonoDevelop do), вы можете сделать это до смешного простым. Все, что вам нужно будет ввести, - это тип свойства и имя свойства. Дополнительные три строки кода будут созданы автоматически.