Интерфейсы определяют поведение объекта.
Статические методы не определяют поведение объекта, но поведение, которое влияет на объект в некотором роде.
Правка: nameof
прибыл в C # 6. Ура!
Нет nameof
/ информации о
и т. Д .; это много обсуждается, но это то, что есть.
Есть способ сделать это с помощью лямбда-выражений в .NET 3.5 (и синтаксического анализа дерева выражений), но на самом деле это не стоит накладных расходов. На данный момент я бы просто придерживался строк (и модульных тестов, если вы настроены не нарушать их).
using System;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
class Program : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
static void Main() {
var p = new Program();
p.PropertyChanged += (s, a) => Console.WriteLine(a.PropertyName);
p.Name = "abc";
}
protected void OnPropertyChanged<T>(Expression<Func<Program, T>> property) {
MemberExpression me = property.Body as MemberExpression;
if (me == null || me.Expression != property.Parameters[0]
|| me.Member.MemberType != MemberTypes.Property) {
throw new InvalidOperationException(
"Now tell me about the property");
}
var handler = PropertyChanged;
if (handler != null) handler(this,
new PropertyChangedEventArgs(me.Member.Name));
}
string name;
public string Name {
get{return name;}
set {
name = value;
OnPropertyChanged(p=>p.Name);
}
}
}
Простейшим решением является просмотр трассировки стека и полное удаление каждой явной ссылки на свойство.
public String Name
{
get { return this.name; }
set
{
if (value != this.name)
{
this.RaisePropertyChanging();
this.name = value;
this.RaisePropertyChanged();
}
}
}
private String name = null;
private void RaisePropertyChanged()
{
String propertyName =
new StackTrace().GetFrame(1).GetMethod().Name.SubString(4);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(new PropertyChangedEventArgs(propertyName));
}
}
Код извлекает имя свойства через трассировку стека из метода вызова, то есть метод установки свойств с именем set_
. Если компилятор больше не следует этому соглашению об именах, код прерывается.
Другое решение - получить имя свойства из лямбда-выражения.
public static String GetPropertyNameFromLambdaExpression<TObject, TProperty>(
Expression<Func<TObject, TProperty>> expression)
{
return ((MemberExpression)expression.Body).Member.Name;
}
Например,
GetPropertyNameFromLambdaExpression<String, Int32>(s => s.Length)
вернет « Длина
» как и ожидалось. Производственная версия кода действительно требует дополнительных проверок и лучшей интеграции с остальной частью кода. Например, можно использовать вывод типа для общих аргументов.
UPDATE
И есть третье решение - вы можете использовать MethodBase. GetCurrentMethod ()
внутри средства получения или установки свойства для получения имени метода установки или получения.
public String Name
{
get { return this.name; }
set
{
if (value != this.name)
{
String propertyName = MethodBase.GetCurentMethod().Name.SubString(4);
this.RaisePropertyChanging(propertyName);
this.name = value;
this.RaisePropertyChanged(propertyName);
}
}
}
private String name = null;
Не ответ на ваш вопрос, но если вы щелкните правой кнопкой мыши-> Рефакторинг-> Переименовать свойство, оно также может переименовать совпадающие строки, включая любые строки, соответствующие имени вашего свойства.
Да, это может быть немного опасно.
Теоретически вы можете использовать MethodBase.GetCurrentMethod (). Name.Substring (4) из установщика свойств. К сожалению, поиск Google показывает, что он, похоже, оказывает значительное влияние на производительность . Еще две вещи, которые следует учитывать:
PropertyChangedEventArgs принимает только один конструктор, которому требуется имя свойства в виде строки. Таким образом, отсутствие использования INotifyPropertyChanged означает, что на каком-то уровне, будь то высокий или низкий в вашей архитектуре, вам придется работать со строкой и переименованием вручную.
Вы должны проверить это сообщение в блоге . Это дает вам возможность сделать следующее:
string propertyName = TypeHelper.GetPropertyName<User>(u => u.LastProjectCode);
PropertyInfo property1 = TypeHelper.GetProperty((SomeClass o) => o.InstanceProperty.Length);
PropertyInfo property2 = TypeHelper.GetProperty(() => SomeClass.StaticProperty.Length);
Переименование в Visual Studio / Resharper / Refactor Pro должно работать на вас.