Вопрос по .net, properties, reflection, c# – Получить имя свойства внутри сеттера

22

Я хочу сохранить свойство между постбэками в приложении ASP.Net. В данный момент занимаюсь этим:

<code>public int MyIndex
{
    get
    {
        return (int)Session[ToString() + "MyIndex"];
    }
}
</code>

но предпочел бы что-то вроде:

<code>public int MyIndex
{
    get
    {
        return (int)Session[ToString() + #code_that_returns_property_name#];
    }
}
</code>

Setter опущен, но он просто помещает значение в Session, используя ту же строку. Есть ли способ использовать отражение или другое лучшее решение?

Похоже, у нас наконец-то естьsyntactic candy coming чтобы решить эту проблему для нас: «Часто вам нужно предоставить строку, которая называет некоторый программный элемент: когда выдается исключение ArgumentNullException, вы хотите назвать виновный аргумент; когда вы вызываете событие PropertyChanged, вы хотите присвоить имя измененному свойству и т. д. & quot;if (x == null) throw new ArgumentNullException(nameof(x)); JMD

Ваш Ответ

6   ответов
12

не существует простого способа сделать то, что вы хотите. я думаю, выmuch лучше с кодом, который вы уже написали.

Edit: This answer has received quite a few downvotes and I do understand why. While it is possible to do what the OP wants to do perhaps we should all stop and think whether or not it is advisable to do so. To paraphrase the immortal words of Доктор Ян МалкомТо, что вы можете сделать что-то, не означает, что вы должны это делать.

Я мог бы опровергнуть это из-за того, что «не существует простого способа сделать то, что вы хотите». Это вводит в заблуждение.
Почему голосование за? это самый разумный ответ ... :) +1 от меня.
+1 от меня тоже, это безумная идея. Если вы обнаружите, что вам приходится много делать, а имя постоянно меняется, поэтому управление им становится бременем, а затем используйте файл .tt для кодирования объявлений свойств или чего-то в этом роде.
+1 за это и принятый ответ. Я могу понять, почему OP хотел бы сделать это, и смягчающий фактор: если рассматриваемое свойство является лишь одним из 40, то есть кое-что, что нужно сказать для одной реализации, которая отделена от 40 жестко-закодированного свойства. имена. Смягчающий фактор является, конечно же, если ОП знает, что эти свойства только установить один или небольшое количество раз, производительность на этом уровне является спорным. Откажитесь от преждевременной оптимизации.
2

чтобы получить имя члена. Это немного скакать, но это работает. Вот код

private string GetPropertyName<TValue>(Expression<Func<BindingSourceType, TValue>> propertySelector)
{
    var memberExpression = propertySelector.Body as MemberExpression;
    if (memberExpression != null)
    {
        return memberExpression.Member.Name;
    }
    else
    {
       return string.empty;    
    }
}

С этим кодом вы можете сделать следующее

return (int)Session[ToString() + GetPropertyName(MyIndex)];

Код безжалостно украден из ответа Ромен в следующей ветке

Get class property name
Какое элегантное решение! +1
Не удается разрешить символ «BindingSourceType» Это проект ASP.Net 3.5 ... Steve Macdonald
Если вы читаете исходный ответ из другого потока, он говорит, что BindingSourceType - это имя класса, которое содержит свойство. Вам нужно использовать имя класса, которому принадлежит свойство MyIndex.
1

ViewState собственность вашего контроля:

public int MyIndex {
    get { 
        object index = ViewState["MyIndex"];
        return (null == index) ? -1 : (int)index;
    }
    set {
        ViewState["MyIndex"] = value;
    }
}
13

CallerMemberName это намного быстрее, и его можно легко скопировать и вставить для дополнительных свойств.

private static object GetSessionValue([CallerMemberName]string propertyName = "") 
{
    return Session[propertyName];
}

private static void SetSessionValue(object value, [CallerMemberName]string propertyName = "") 
{
    Session[propertyName] = value;
}

public int MyIndex
{
    get { return (int)GetSessionValue(); }
    set { SetSessionValue(value); }
}
Этот ответ - лучший способ, поскольку он работает во время компиляции, а не во время выполнения.
7

чтобы вернуть имя текущего метода:

public int MyIndex
{
    get
    {
        return (int)Session[ToString() + MethodInfo.GetCurrentMethod().Name];
    }
}

Поскольку свойства реализованы как внутренние методы, они будут возвращать имя, подобное & quot; get_MyIndex & quot ;. Если вы не хотите & quot; get_ & quot; часть, вы можете вычленить несколько символов:

public int MyIndex
{
    get
    {
        return (int)Session[ToString() + MethodInfo.GetCurrentMethod().Name.Substring(4)];
    }
}
23
public static int Dummy {
    get {
        var propertyName = MethodBase.GetCurrentMethod().Name.Substring(4);
        Console.WriteLine(propertyName);
        return 0;
    }
}
В дополнение к другим комментариям этот метод будет в сотни (тысячи?) Раз медленнее, отражение не является дешевым. Это может не беспокоить ОП, но любой, кто задумывается над этим, должен знать об этом. (простой тест на моей машине, версия отражения заняла 71 секунду для 10000000 вызовов, версия с жестким кодом заняла 0,8 секунды)
Нет, это сработало. Не уверен, откуда это исключение. Работает нормально сейчас. Как раз то, что мне было нужно. Steve Macdonald
GetCurrentMethod () возвратил System.ArgumentException для меня ... Steve Macdonald
Смотрите мой ответ, который использует CallerMemberName для решения проблемы скорости.
Ради любви к Богу, нет! Результат в пять раз длиннее и в 100 раз более непонятен, чем то, что он заменил! Если вы не собираетесь постоянно передумать, как назвать это свойство, это нелепая идея. (... ПО МОЕМУ МНЕНИЮ)

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